将参数从bash传递给perl而不使用ARGV

zzx*_*xyz 1 bash perl xargs

非常简单的问题(我认为)我很惊讶我似乎无法找到答案.所以到目前为止我有以下内容:

£ 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|
Run Code Online (Sandbox Code Playgroud)

所以....第一个管道是因为文件是1.5G,所以不进行记录分离最初会大大加快速度.这xargs部分是为了展示我正在尝试做的事情.这基本上如下

| xargs -i perl --setperlvar pipeContents={} -ane 'print if $F[3] =~ /$pipeContents/' 15AM171H0N15000GAJK5
Run Code Online (Sandbox Code Playgroud)

1)我知道我可以在脚本中使用ARGV.我知道整件事应该只是一个脚本.我们忽略这些位.我的爱-n无所不知.

2)对不起,我自己也找不到了......我很确定这是非常明显的......虽然我在perldoc做了一些挖掘但没有找到任何东西.

3)我对bash/zsh解决方案感兴趣,该解决方案也强制{}在perl ticks的中间由shell解释.

ike*_*ami 5

我开始之前的两点说明:

  • |模式中的尾随将导致每一行匹配.它需要被删除.
  • /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
Run Code Online (Sandbox Code Playgroud)

Perl还有一个内置的参数解析函数,-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
Run Code Online (Sandbox Code Playgroud)

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 {}
Run Code Online (Sandbox Code Playgroud)

涉及xargs一条线是很奇怪的.如果我们避免xargs,我们可以将上面(丑陋)的命令翻出来,给出一些非常好的东西.

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
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您不需要秒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
Run Code Online (Sandbox Code Playgroud)

也就是说,我认为$ENV{P}应该避免反复使用以加快速度.

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

从那里,我看到两种可能的速度改进.(测试一下.)

  1. 避免完全分裂perl.

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

    P=... perl -ane'
       BEGIN { %h = map { $_ => 1 } split /\|/, $ENV{P} }
       print if $h{$F[3]};
    ' 15AM171H0N15000GAJK5
    
    Run Code Online (Sandbox Code Playgroud)