【问题标题】:Perl Filter using cmd and piped argumentsPerl 过滤器使用 cmd 和管道参数
【发布时间】:2017-11-06 06:34:27
【问题描述】:

我正在编写一个 Perl 脚本 (filter.pl),它过滤 STDIN 上显示的数据,将一个字符串的所有出现更改为另一个字符串,并将所有输入行输出,更改和未更改到 STDOUT。我的用法如下:

USAGE: ./filter.pl 'FROMSTRING' 'TOSTRING'

例如,这是我运行脚本的方式:

echo "this is a test" | filter.pl 'a' '@'
#output: "this is @ test"

到目前为止,这是我的代码:

#!/usr/bin/perl
use strict;
use warnings;

#Verify two cmd arguments are present.     
if ($#ARGV !=2)
    {
    print "Usage: ./filter.pl FROMSTRING TOSTRING";
    exit(1);
    }

#read from STDIN, replace FROMSTRING with TOSTRING, then print output
while (<>)
    {
    s/$ARGV[0]/$ARGV[1]/gi;
    print $_;
    exit(0);
    }

基本上这个脚本使用“(STDIN)”来读取每一行输入,使用$_来访问每一行读取,使用“s///将每行上所有出现的FROMSTRING更改为TOSTRING,并将它们打印出来.

当我从命令行运行它时,我得到一个错误:找不到命令。我怀疑这是因为我不知道 Perl 中管道输入和调用参数之间的区别?还想知道我是否在正确的轨道上。

谢谢。

【问题讨论】:

  • #1 如何调用脚本?该错误可能与 Perl 代码无关。 #2 很可能您不想在处理完第一行后终止程序。所以删除exit(0);
  • filter.pl 是否可执行并在您的PATH 中? (另外,将 exit(0); 移到您的 while 循环之后。)
  • 哦,我没有意识到我的 exit(0) 在我的 while 语句中。将它移出,现在它工作正常。谢谢!!!
  • 另外:$#ary@ary 中最后一个元素的索引。所以你对$#ARGV 的条件要求@ARGV 的最后一个元素具有索引2,因此@ARGV 具有索引0, 1, 2三个元素。你想要的是@ARGV != 2
  • "Command not found" 可能是因为没有使filter.pl 可执行。

标签: regex perl stdin argv


【解决方案1】:

&lt;&gt;&lt;ARGV&gt; 的简写,其中ARGV 是一个特殊的文件句柄,它既可以引用标准输入,也可以引用@ARGV 中所有文件名的输入流。

由于您的脚本将@ARGV 用于指定输入文件以外的目的,因此您不能使用ARGV 从标准输入中读取。您应该明确使用&lt;STDIN&gt; 从标准输入读取而不是&lt;&gt;

while (<STDIN>)
{
    s/$ARGV[0]/$ARGV[1]/gi;
    print $_;
    exit(0);       # <---- this probably belongs outside the loop
}

【讨论】:

  • 一个更好的解决方案是去掉@ARGV的前两个元素:die("Usage: ...\n") if @ARGV &lt; 2; my ($pat, $repl) = splice(@ARGV, 0, 2); while (&lt;&gt;) { ...; s/$pat/$repl/gi; ... }
猜你喜欢
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-12
相关资源
最近更新 更多