为什么“perl -F”与“perl -F”的工作方式不同'

为什么“perl -F”与“perl -F”的工作方式不同'

这符合我的预期(当 column2 更改值时):

$ (echo 'a,,b';echo 'b,,a';echo 'c,a,b') |
    perl -a '-F,' -pe 'BEGIN{$last="---\n";}{local$_=$F[1];if(($last)ne$_){print"---\n";$last=$_;}}'
---
a,,b
b,,a
---
c,a,b

这不会:

$ (echo 'a  b';echo 'b  a';echo 'c a b') |
    perl -a '-F ' -pe 'BEGIN{$last="---\n";}{local$_=$F[1];if(($last)ne$_){print"---\n";$last=$_;}}'
---
a  b
b  a
c a b

答案1

-a记录到 using split(),并且 perlfunc 手册页对此进行了说明:

作为另一个特殊情况,当 PATTERN 被省略或由单个空格字符(例如 ' 'or "\x20",但不是 eg "/ /")组成的字符串时,“split”模拟命令行工具 awk 的默认行为。在这种情况下,EXPR 中的任何前导空格都会在拆分发生之前被删除,并且 PATTERN 会被视为"/\s+/";特别是,这意味着任何连续的空格(不仅仅是单个空格字符)都用作分隔符。

所以我想-F\040是这样的。由于某种原因,[\040]似乎也这样做。 (如果我不得不猜测,我会假设它被优化为固定字符串,然后被视为特殊情况。)

$ echo 'a b  c' | perl -a -F'\040'  -le 'print join(":", @F)'
a:b:c
$ echo 'a b  c' | perl -a -F'[\040]'  -le 'print join(":", @F)'
a:b:c

另一方面,\040{1}似乎做你想做的事,并且不将制表符识别为分隔符:

$ echo 'a b  c' | perl -a -F'\040{1}'  -le 'print join(":", @F)'
a:b::c
$ printf 'a b\t c' | perl -a -F'\040{1}'  -le 'print join(":", @F)'
a:b     :c

或者我猜你可以split使用模式而不是字符串手动显式调用:

$ printf 'a b\t c' | perl -n -le '@F = split(/ /); print join(":", @F)'
a:b     :c

(我使用 Perl v5.24.1 和 v5.28.1 进行了测试。)

答案2

man perlrun

-Fpattern [...] 不能在模式中使用文字空白或 NUL 字符。

但是你使用 \040:

$ (echo 'a  b';echo 'b  a';echo 'c a b') |   perl -a '-F\040' -pe 'BEGIN{$last="---\n";}{local$_=$F[1];if(($last)ne$_){print"---\n";$last=$_;}}'
---
a  b
---
b  a
c a b

不幸的是,它似乎被解释为一个或者更多空格(这也是 -F 的默认值),这不是我想要的。

\s 效果更好,但\t也匹配:

$ (printf 'a\t b\n';echo 'b  a';echo 'c a b') |   perl -a '-F\s' -pe 'BEGIN{$last="---\n";}{local$_=$F[1];if(($last)ne$_){print"---\n";$last=$_;}}'
---
a        b
b  a
---
c a b

相关内容