perl中字段分隔符的变量

时间:2011-06-23 22:37:31

标签: perl awk

在awk中我可以写:awk -F: 'BEGIN {OFS = FS} ...'

在Perl中,相当于FS的是什么?我想写

perl -F: -lane 'BEGIN {$, = [what?]} ...'

使用示例进行更新:

echo a:b:c:d | awk -F: 'BEGIN {OFS = FS} {$2 = 42; print}'
echo a:b:c:d | perl -F: -ane 'BEGIN {$, = ":"} $F[1] = 42; print @F'

输出a:42:c:d

我不想在Perl BEGIN块中对:进行硬编码,而是在-F选项保存其参数的任何地方引用。

5 个答案:

答案 0 :(得分:6)

总而言之,我所寻找的东西不存在:

  1. 没有变量保存-F的参数,更重要的是
  2. Perl的“FS”基本上是与“OFS”(字符串)不同的数据类型(正则表达式) - 使用正则表达式连接字符串列表没有意义。
  3. 请注意,在awk中也是如此:FS是一个字符串,但作为正则表达式:

    echo a:b,c:d | awk -F'[:,]' 'BEGIN {OFS=FS} {$2=42; print}'
    

    输出“a[:,]42[:,]c[:,]d

    感谢您的见解和解决方法。

答案 1 :(得分:2)

如果你知道确切的输入长度,你可以这样做:

echo a:b:c:d | perl -F'(:)' -ane '$, = $F[1]; @F = @F[0,2,4,6]; $F[1] = 42; print @F'

如果输入的长度可变,你需要比@f [0,2,4,6]更复杂的东西。

编辑: -F似乎只是为自动split()调用提供输入,它将完整的RE作为表达式。您可以通过阅读拆分 perlre perlvar 的perldoc条目找到更合适的内容。

答案 2 :(得分:1)

... Darnit

我能做的最好的事情是:

echo a:b:c:d | perl -ne '$v=":";@F = split("$v"); $F[1] = 42; print join("$v", @F) . "\n";'

你不需要-F:这种方式,你只需要说一次冒号。我希望在命令行上设置变量,就像使用Awk的-v开关一样。

对于一个衬垫,Perl通常不像Awk那样干净,但我记得在我知道Perl并编写1000多行awk脚本之前使用Awk。

尝试这样的事情让人们认为Awk的名字取决于某人试图破译这样一个剧本时的声音,或代表AWKward。

答案 3 :(得分:1)

你可以排序欺骗它,因为perl实际上正在使用split函数与你的-F参数,你可以告诉split保留什么它通过在正则表达式中捕获parens来分裂:

$ echo a:b:c:d | perl -F'(:)' -ane 'print join("/", @F);'
a/:/b/:/c/:/d

您可以使用-MO=Deparse查看perl使用$ perl -MO=Deparse -F'(:)' -ane 'print join("/", @F);' LINE: while (defined($_ = <ARGV>)) { our(@F) = split(/(:)/, $_, 0); print join('/', @F); } -e syntax OK 执行某些“神奇”命令行参数的操作,如下所示:

@F

您必须将$F[2] = 42下标更改为他们通常的两倍({{1}})。

答案 4 :(得分:0)

Perl中没有输入记录分隔符。您基本上是使用-a-F标志来模拟awk。如果你真的不想对值进行硬编码,那么为什么不使用环境变量?

$ export SPLIT=":"
$ perl -F$SPLIT -lane 'BEGIN { $, = $ENV{SPLIT}; } ...'