简体   繁体   English

perl 中字段分隔符的变量

[英]variable for field separator in perl

In awk I can write: awk -F: 'BEGIN {OFS = FS} ...'在 awk 我可以写: awk -F: 'BEGIN {OFS = FS} ...'

In Perl, what's the equivalent of FS ?在 Perl 中, FS的等价物是什么? I'd like to write我想写

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

update with an example:更新一个例子:

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'

Both output a:42:c:d都输出a:42:c:d

I would prefer not to hard-code the : in the Perl BEGIN block, but refer to wherever the -F option saves its argument.我不想对 Perl BEGIN 块中的:进行硬编码,而是引用-F选项保存其参数的位置。

To sum up, what I'm looking for does not exist:总而言之,我要找的东西不存在:

  1. there's no variable that holds the argument for -F , and more importantly没有变量可以保存-F的参数,更重要的是
  2. Perl's "FS" is fundamentally a different data type (regular expression) than the "OFS" (string) -- it does not make sense to join a list of strings using a regex. Perl 的“FS”从根本上是一种与“OFS”(字符串)不同的数据类型(正则表达式)——使用正则表达式连接字符串列表是没有意义的。

Note that the same holds true in awk: FS is a string but acts as regex:请注意,在 awk 中也是如此: FS是一个字符串,但充当正则表达式:

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

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

Thanks for the insight and workarounds though.不过,感谢您的洞察力和解决方法。


You can use perl's -s (similar to awk's -v ) to pass a "FS" variable, but the split becomes manual:您可以使用 perl 的-s (类似于 awk 的-v )传递“FS”变量,但split变为手动:

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

If you know the exact length of input, you could do this:如果你知道输入的确切长度,你可以这样做:

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

If the input is of variable lengths, you'll need something more sophisticated than @f[0,2,4,6].如果输入的长度可变,您将需要比@f[0,2,4,6] 更复杂的东西。

EDIT: -F seems to simply provide input to an automatic split() call, which takes a complete RE as an expression.编辑: -F 似乎只是为自动 split() 调用提供输入,该调用将完整的 RE 作为表达式。 You may be able to find something more suitable by reading the perldoc entries for split , perlre , and perlvar .您可以通过阅读splitperlreperlvar的 perldoc 条目找到更合适的内容。

Darnit...达尼特...

The best I can do is:我能做的最好的是:

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

You don't need the -F: this way, and you're only stating the colon once.你不需要-F:这样,你只声明一次冒号。 I was hoping there was someway of setting variables on the command line like you can with Awk's -v switch.我希望有某种方式在命令行上设置变量,就像使用 awk 的-v开关一样。

For one liners, Perl is usually not as clean as Awk, but I remember using Awk before I knew of Perl and writing 1000+ line Awk scripts.对于一个班级来说,Perl 通常不如 Awk 干净,但我记得在我知道 Perl 之前使用 Awk 并编写了 1000 多行 Awk 脚本。

Trying things like this made people think Awk was either named after the sound someone made when they tried to decipher such a script, or stood for AWKward.尝试这样的事情让人们认为 awk 要么以某人试图破译这样的脚本时发出的声音命名,要么代表 AWKward。

You can sort of cheat it, because perl is actually using the split function with your -F argument, and you can tell split to preserve what it splits on by including capturing parens in the regex:您可以排序的欺骗,因为是用perl实际使用split功能与-F参数,你可以告诉split保留通过在正则表达式捕获括号它分裂的:

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

You can see what perl's doing with some of these "magic" command-line arguments by using -MO=Deparse , like this:您可以通过使用-MO=Deparse来查看 perl 对其中一些“神奇”命令行参数的-MO=Deparse ,如下所示:

$ perl -MO=Deparse -F'(:)' -ane 'print join("/", @F);'
LINE: while (defined($_ = <ARGV>)) {
    our(@F) = split(/(:)/, $_, 0);
    print join('/', @F);
}
-e syntax OK

You'd have to change your @F subscripts to double what they'd normally be ( $F[2] = 42 ).您必须将@F下标更改为通常情况下的两倍( $F[2] = 42 )。

There is no input record separator in Perl. Perl 中没有输入记录分隔符。 You're basically emulating awk by using the -a and -F flags.您基本上是通过使用-a-F标志来模拟 awk。 If you really don't want to hard code the value, then why not just use an environmental variable?如果您真的不想对值进行硬编码,那么为什么不使用环境变量呢?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM