【问题标题】:How do I best pass arguments to a Perl one-liner?我如何最好地将参数传递给 Perl 单行器?
【发布时间】:2010-07-23 19:46:35
【问题描述】:

我有一个文件,someFile,如下所示:

$cat someFile
hdisk1 active
hdisk2 active

我用这个shell脚本来检查:

$cat a.sh
#!/usr/bin/ksh
for d in 1 2
do
    grep -q "hdisk$d" someFile && echo "$d : ok"
done

我正在尝试将其转换为 Perl:

$cat b.sh
#!/usr/bin/ksh
export d
for d in 1 2
do
    cat someFile | perl -lane 'BEGIN{$d=$ENV{'d'};} print "$d: OK" if /hdisk$d\s+/'
done

我在 shell 脚本中导出变量 d 并在 Perl 中使用 %ENV 获取值。有没有更好的方法将此值传递给 Perl 单行器?

【问题讨论】:

  • 为什么不直接在 Perl 中执行循环呢?然后你的 shell 脚本就消失了。
  • 使用cat file | perl ... 比使用perl ... file 更简单。

标签: perl


【解决方案1】:

您可以使用“s”开关启用基本的命令行参数。为每个以破折号开头的参数定义一个变量。 -- 告诉你的命令行参数从哪里开始。

for d in 1 2 ; do 
  cat someFile | perl -slane ' print "$someParameter: OK" if /hdisk$someParameter\s+/' -- -someParameter=$d; 
done

见:perlrun

【讨论】:

  • 非常感谢。从来没有真正想通。需要命令行参数时总是编写脚本。
【解决方案2】:

有时打破 Perl 外壳对于这些单行代码来说是一个好技巧:

for d in 1 2 ; do cat kk2 | perl -lne ' print "'"${d}"': OK" if /hdisk'"${d}"'\s+/';done

【讨论】:

    【解决方案3】:

    在命令行中传递它,它将在@ARGV中可用:

    for d in 1 2
    do
      perl -lne 'BEGIN {$d=shift} print "$d: OK" if /hdisk$d\s+/' $d someFile
    done
    

    请注意,此上下文中的 shift 运算符删除了 @ARGV 的第一个元素,在本例中为 $d

    【讨论】:

    • 值得指出的是@gbacon 已将cat a| perl -n 转换为perl -n a。如果您将文件名作为参数提供给 perl,则它可用于 -n 循环。
    【解决方案4】:

    如果您在编写单行时遇到困难,那么单行可能有点难(仅我的看法)。我同意@FM 的建议,并在 Perl 中完成所有工作。读入整个文件然后测试它:

        use strict;
        local $/ = '' ; # Read in the whole file
        my $file = <> ;
    
        for my $d ( 1 .. 2 )
        {
            print  "$d: OK\n" if  $file =~ /hdisk$d\s+/
        }
    

    你可以循环播放,但这会更长。当然,这在一定程度上取决于文件的大小。

    请注意,到目前为止,所有 Perl 示例都会为每个匹配项打印一条消息 - 你能确定没有重复吗?

    【讨论】:

      【解决方案5】:

      结合之前的一些建议并添加我自己的糖,我会这样做:

      perl -se '/hdisk([$d])/ && print "$1: ok\n" for <>' -- -d='[value]' [file]
      

      [value] 可以是数字(即 2)、范围(即 2-4)、不同数字的列表(即 2|3|4)(或几乎任何其他值,这是一个有效的模式)甚至包含其中之一的 bash 变量,例如:

      d='2-3'
      perl -se '/hdisk([$d])/ && print "$1: ok\n" for <>' -- -d=$d someFile 
      

      [file] 是您的文件名(即someFile)。

      【讨论】:

        【解决方案6】:

        我的解决方案有点不同。我通过谷歌搜索你的问题的标题来回答你的问题,但我正在尝试执行一些不同的操作。这是以防万一它对某人有帮助:

        仅供参考,我在 Solaris 上使用 tcsh

        我有以下单行:

        perl -e 'use POSIX qw(strftime); print strftime("%Y-%m-%d", localtime(time()-3600*24*2));'
        

        输出值:

        2013-05-06
        

        我试图将它放入一个 shell 脚本中,这样我就可以创建一个文件名中包含 X 天过去日期的文件。我试过了:

        set dateVariable=`perl -e 'use POSIX qw(strftime); print strftime("%Y-%m-%d", localtime(time()-3600*24*$numberOfDaysPrior));'`
        

        但是由于变量替换,这不起作用。我不得不弄乱引用,让它正确解释它。我尝试用双引号将全部内容括起来,但这使得 Perl 命令在语法上不正确,因为它与日期格式周围的双引号混淆了。我完成了:

        set dateVariable=`perl -e "use POSIX qw(strftime); print strftime('%Y-%m-%d', localtime(time()-3600*24*$numberOfDaysPrior));"`
        

        这对我来说非常有用,无需求助于任何花哨的变量导出。

        我知道这并不能完全回答您的具体问题,但它回答了标题并可能对其他人有所帮助!

        【讨论】:

          【解决方案7】:

          看起来不错,但我会使用:

          for d in $(seq 1 2); do perl -nle 'print "hdisk$ENV{d} OK" if $_ =~ /hdisk$ENV{d}/' someFile; done
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-12-08
            • 1970-01-01
            • 1970-01-01
            • 2011-12-28
            • 1970-01-01
            • 2015-01-29
            相关资源
            最近更新 更多