代码之家  ›  专栏  ›  技术社区  ›  zzxyz

在不使用ARGV的情况下将参数从bash传递到perl

  •  1
  • zzxyz  · 技术社区  · 6 年前

    £ perl -ne 'print if /ENGPacific Beach\s\s/' 15AM171H0N15000GAJK5 \
    | perl -ane 'print "$F[1]|";END{print "\0"}' | xargs -i -0 echo {}
        3346|10989|95459|139670|2239329|3195595|3210017|
    

    所以…第一个管道是因为文件是1.5G,所以不做记录分离最初会大大加快速度。这个 xargs

    | xargs -i perl --setperlvar pipeContents={} -ane 'print if $F[3] =~ /$pipeContents/' 15AM171H0N15000GAJK5
    

    1) 我知道我可以在脚本中使用ARGV。我知道整件事应该只是一个剧本。让我们忽略那些细节。我的爱 -n 没有界限。

    {} 也可以由perl记号中间的shell解释。

    2 回复  |  直到 6 年前
        1
  •  5
  •   ikegami    6 年前

    开始前有两个注意事项:

    • | 在模式中会导致每一行匹配。它需要被移除。
    • /3346|10989|95459|139670|2239329|3195595|3210017/ 将匹配 9993346 ,所以你需要锚定模式。

    以下所有解决方案都提供了解决这些问题的方法。


    你可以通过

    • 环境
    • 管道的开放文件描述符(例如stdin,但也可以使用fd 3或更高版本)
    • 外部存储(文件、数据库、memcache守护进程等)

    @ARGV 在循环开始之前使用 BEGIN 或者逃避 -n .

    perl -ne'print if /ENGPacific Beach\s\s/' 15AM171H0N15000GAJK5 |
    perl -ane'push @p, $F[1]; END { print join "|", @p; }' |
    xargs -i perl -ane'
        BEGIN { $p = shift(@ARGV); }
        print if $F[3] =~ /^(?:$p)\z/;
    ' {} 15AM171H0N15000GAJK5
    

    -s 你可以利用。

    perl -ne'print if /ENGPacific Beach\s\s/' 15AM171H0N15000GAJK5 |
    perl -ane'push @p, $F[1]; END { print join "|", @p; }' |
    xargs -i perl -sane'print if $F[3] =~ /^(?:$p)\z/' -- -p={} 15AM171H0N15000GAJK5
    

    xargs 似乎没有设置环境变量的选项,所以采用这种方法有点复杂。

    perl -ne'print if /ENGPacific Beach\s\s/' 15AM171H0N15000GAJK5 |
    perl -ane'push @p, $F[1]; END { print join "|", @p; }' |
    xargs -i sh -c '
        P="$1" perl -ane'\''print if $F[3] =~ /^(?:$ENV{P})\z/'\'' 15AM171H0N15000GAJK5
    ' dummy {}
    

    有点奇怪 参数代换 参数代换 ,我们可以将上面的(丑陋的)命令翻过来,给出一些很好的结果。

    P="$(
        perl -ne'print if /ENGPacific Beach\s\s/' 15AM171H0N15000GAJK5 |
        perl -ane'push @p, $F[1]; END { print join "|", @p; }'
    )" perl -ane'print if $F[3] =~ /^(?:$ENV{P})\z/' 15AM171H0N15000GAJK5
    

    perl 只分割匹配的行。

    P="$(
        perl -ne'
           push @p, (split)[1] if /ENGPacific Beach\s\s/;
           END { print join "|", @p; }
        ' 15AM171H0N15000GAJK5
    )" perl -ane'print if $F[3] =~ /^(?:$ENV{P})\z/' 15AM171H0N15000GAJK5
    

    也就是说,我想用 $ENV{P}

    P=... perl -ane'print if $F[3] =~ /^(?:$ENV{P})\z/o' 15AM171H0N15000GAJK5
    

    从那里,我看到两个可能的速度改进。(一定要测试。)

    1. 避免最后完全分裂 .

      P=... perl -ne'
         BEGIN { $re = qr/^(?:\S+\s+){3}(?:$ENV{P})\s/o; }
         print if /$re/o;
      ' 15AM171H0N15000GAJK5
      
    2. 完全避免在最后使用正则表达式 .

      P=... perl -ane'
         BEGIN { %h = map { $_ => 1 } split /\|/, $ENV{P} }
         print if $h{$F[3]};
      ' 15AM171H0N15000GAJK5
      
        2
  •  2
  •   zdim    6 年前

    传递参数的简便方法是通过 -s switch

    perl -s -E'say $var' -- -var=value
    

    这个 -- -var 引入变量 $var 输入到程序中,并在 = -风险价值 变量 获取值 1 .

    任何这样的选项必须在可能的文件名之前,并且从 @ARGV

    perl -s -ne'...' -- -var="$SHELL_VAR" filename
    

    哪里 -var={} 也行。在一些贝壳里( tcsh \{\} .

    不过,我也认为最好不要去 xargs . 见 ikegami's answer -s公司 .