首页 > 解决方案 > Perl 中的 eval gawk,如何处理引号?

问题描述

我有一个看起来像这样的文件:

NameA X Y 0 Add1
NameA X Y 1 Add1
NameB X Y 1 Add1
NameB X Y 0 No
NameB X Y 1 No

我正在通过 gawk 运行它,如下所示:

gawk -v OFS='\t' workdir=$workdir '{FS = OFS} {if ($0 ~ /Add1/) {print $2, $3, $4 + 1, $5"_done" >> workdir"/"$1; close($1)} else {print $2, $3, $4, $5"_done" >> workdir"/"$1; close($1)}}' input_file.txt

预期的输出是:

workdir/NameA:
NameA X Y 1 Add1
NameA X Y 2 Add1

workdir/NameB:
NameB X Y 2 Add1
NameB X Y 0 No
NameB X Y 1 No

效果很好,

我现在想使用 perl 将其合并到工作流中,并将其写在此块中:

else    {
    my $gawk = "gawk -v OFS='\t' workdir=$workdir '{FS = OFS} {if ($0 ~ /Add1/) {print $2, $3, $4 + 1, $5"_done" >> workdir"/"$1; close($1)} else {print $2, $3, $4, $5"_done" >> workdir"/"$1; close($1)}}' $input";
    eval {
       `$gawk`;
      };

where$workdir$input前面已经定义了。

我遇到了这个错误:

String found where operator expected at xxxxx.pl line 511 near $5"_done""

我想我在某处搞砸了引号,但任何输入都会有所帮助!

标签: perlawk

解决方案


问题 #1:您没有正确构造字符串文字。具体来说,当您希望它生成包含这些字符的字符串时\,需要在双引号字符串文字中对其进行转义。$"

问题 #2:您没有正确构建您的 shell 命令。具体来说,您没有正确地将$workdirand的值转换$input为 shell 字符串文字。这是危险的。

-v问题 #3:您在尝试设置时缺少 a $workdir

使固定:

use String::ShellQuote qw( shell_quote );

my $gawk_prog = <<'__END_OF_CMD__';
   ...Put nicely formatted gawk code here...
__END_OF_CMD__

my $shell_cmd = shell_quote(
   "gawk",
   -v => "OFS=\\t",
   -v => "workdir=$workdir",
   $gawk_prog,
   $input,
);

my $output = `$shell_cmd`;
die("gawk killed by signal ".( $? & 0x7F )."\n") if $? & 0x7F;
die("gawk exited with error ".( $? >> 8 )."\n") if $? >> 8;

注意:您可以BEGIN { OFS = "\t" }在程序中使用而不是使用-v来设置OFS为常数值。

注意:使用没有意义,eval因为readpipe(反引号)不会引发异常。

注意:在单引号 heredocs 中,\除了终止标记之外,没有什么特别的——甚至反斜杠 ( ) 也没有。这使得生成由代码组成的字符串非常方便。

注意:您要求gawk做的事情可以在 Perl 中轻松完成。


推荐阅读