【发布时间】:2016-01-18 21:46:07
【问题描述】:
以下简单脚本(基本上)在其输入中进行 slurp,根据正则表达式对其进行拆分,替换结果列表中每个元素中的所有换行符,并逐个打印出修改后的元素:
# demo.pl
use strict;
use utf8;
use open qw(:std :utf8);
use warnings qw(FATAL utf8);
BEGIN { $/ = $\ = undef; }
while ( <> ) {
s/\n\z//;
s/\n/\\n/g, print "$_\n" for split /\n(?=[^\W\d]\w*=)/;
}
当给定输入文件 (INPUTFILE) 时,其参数包含以下(UTF8 编码)内容
A=42
ΦΡΩΒΩΖΖ=ABCDEFGHIJKLMNOPQRSTUVWXYZ
_B_C_D12=
foo
345bar=nope
baz
=whatever=
X_Y_Z=quux
...它打印出所需的输出,即:
% perl demo.pl INPUTFILE
A=42
ΦΡΩΒΩΖΖ=ABCDEFGHIJKLMNOPQRSTUVWXYZ
_B_C_D12=\nfoo\n345bar=nope\nbaz\n =whatever=
X_Y_Z=quux
相比之下,以下几乎相同的 CLI 单行代码
% perl -ne 'use strict; use utf8; use open qw(:std :utf8); use warnings qw(FATAL utf8); BEGIN { $/ = $\ = undef; } s/\n\z//; s/\n/\\n/g, print "$_\n" for split /\n(?=[^\W\d]\w*=)/;' INPUTFILE
...为相同的输入文件生成以下内容
A=42\nΦΡΩÎΩÎÎ=ABCDEFGHIJKLMNOPQRSTUVWXYZ
_B_C_D12=\nfoo\n345bar=nope\nbaz\n =whatever=
X_Y_Z=quux
这里(显然)有两个问题:
- 正则表达式无法分隔第一项和第二项;
- 输出包含难以辨认的子字符串。
(我希望这两个问题都有相同的根本原因。)
“文件内脚本”(demo.pl) 和 CLI 单行之间的唯一区别是前者明确地用while ( <> ) { ... } 包裹脚本的主体,而对于后者,-n flag 导致这个包装器被自动插入。
问:必须如何修改上面的单行代码,以便产生所需的结果带有-n 标志?
顺便说一句,demo.pl(没有 -n 标志)的 exact 命令行等价物也就不足为奇了,即
% perl -e 'use strict; use utf8; use open qw(:std :utf8); use warnings qw(FATAL utf8); BEGIN { $/ = $\ = undef; } while ( <> ) { s/\n\z//; s/\n/\\n/g, print "$_\n" for split /\n(?=[^\W\d]\w*=)/; }' INPUTFILE
还会产生所需的输出。
所以无论是什么问题,都与-n 标志有关。
FWIW:
% perl -v | head -2
This is perl 5, version 20, subversion 2 (v5.20.2) built for x86_64-linux-gnu-thread-multi
编辑:还有一条线索:如果失败的单线的输入是通过STDIN 而不是@ARGV 中的文件名(例如,用< INPUTFILE 替换INPUTFILE),那么它会产生所需的输出完全清晰,虽然仍然不正确,输出:
A=42\nΦΡΩΒΩΖΖ=ABCDEFGHIJKLMNOPQRSTUVWXYZ
_B_C_D12=\nfoo\n345bar=nope\nbaz\n =whatever=
X_Y_Z=quux
我目前的猜测是use open qw(:std :utf8) 不包括<> 在@ARGV 中将输入作为文件名传递时从中读取的输入流。
【问题讨论】:
标签: regex unicode command-line perl