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

时间:2018-08-13 20:34:45

标签: 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|

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

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

1)我知道我可以在脚本中使用ARGV。我知道整个事情应该只是一个脚本。让我们忽略这些位。我对-n的爱无止境。

2)对不起,我自己也找不到。.我敢肯定,这是显而易见的...我在perldoc中做了一些挖掘,但是什么也没发现。

3)我会对bash / zsh解决方案感兴趣,该解决方案也迫使{}也由shell在perl滴答声的中间解释。

2 个答案:

答案 0 :(得分:5)

开始之前请注意两个事项:

  • 模式中的结尾my-app/public/Videos/video1.mp4将导致每一行都匹配。需要将其删除。
  • |将与/3346|10989|95459|139670|2239329|3195595|3210017/匹配,因此您需要锚定模式。

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


您可以通过以下方式将数据传递给程序

  • 参数列表
  • 环境
  • 打开文件描述符(例如stdin,但也可以使用fd 3或更高版本)
  • 外部存储(文件,数据库,memcache守护程序等)

您仍然可以使用参数列表。您只需在循环开始之前通过使用9993346或避免使用@ARGVBEGIN中删除参数。

-n

Perl还可以使用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 {} 很奇怪。如果我们避免使用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 仅分割匹配的行。

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}

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

  1. 避免在最后一个P=... perl -ane'print if $F[3] =~ /^(?:$ENV{P})\z/o' 15AM171H0N15000GAJK5 中完全拆分。

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

    perl

答案 1 :(得分:2)

一种方便的传递参数的方法是通过-s switch,它可以启用程序的命令行开关

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

程序后的--标志着程序参数的开始。然后-var将变量$var引入程序,并在=之后提供其值;外壳首先扩展了那里的内容。仅使用-var,变量$var就得到值1

任何此类选项必须在可能的文件名之前,并将它们从@ARGV中删除,以便程序可以正常处理提交的文件

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

-var={}也在哪里工作。在某些shell中(tcsh为一个),可能需要转义\{\}

但是,我也认为最好不要去xargs。请参阅ikegami's answer,以进行全面的讨论和各种方式,以及他们在本文下方的评论中,了解如何通过-s避免出现这种情况。