5

我正在尝试解决如何使用 perl(来自 shell)来匹配换行符。下列的:

(echo a b c d e; echo f g h i j; echo l m n o p) | perl -pe 's/(c.*)/[$1]/'

我明白了:

a b [c d e]
f g h i j
l m n o p

这是我所期望的。但是当我/s在我的正则表达式末尾放置一个时,我得到了这个:

a b [c d e
]f g h i j
l m n o p

我期望并希望它打印的是:

a b [c d e
f g h i j
l m n o p
]

我的正则表达式有问题,还是我的 perl 调用标志有问题?

4

5 回答 5

12

-p逐行循环输入,其中“行”由$/输入记录分隔符分隔,默认情况下是换行符。如果您想将所有 STDIN 插入$_以进行匹配,请使用-0777.

$ echo "a b c d e\nf g h i j\nl m n o p" | perl -pe 's/(c.*)/[$1]/s'
a b [c d e
]f g h i j
l m n o p
$ echo "a b c d e\nf g h i j\nl m n o p" | perl -0777pe 's/(c.*)/[$1]/s'
a b [c d e
f g h i j
l m n o p
]

有关这两个标志的信息,请参阅perlrun 中的命令开关。-l(dash-ell) 也很有用。

于 2012-12-18T07:01:50.650 回答
2

问题是你的单行一次只工作一行,你的正则表达式很好:

use strict;
use warnings;
use 5.014;

my $s = qq|a b c d e
f g h i j
l m n o p|;

$s =~ s/(c.*)/[$1]/s;

say $s;
于 2012-12-18T07:04:30.947 回答
1

实际上你的单线看起来像这样:

while (<>) {

     $ =~ s/(c.*)/[$1]/s;
}

这意味着正则表达式仅适用于您输入的第一行。

于 2012-12-18T07:01:57.610 回答
1

有不止一种方法可以做到这一点:既然你正在阅读“一次整个文件”,我会亲自删除-p修饰符,明确地吞下整个输入,然后从那里开始:

echo -e "a b c d e\nf g h i j\nl m n o p" | perl -e '$/ = undef; $_ = <>; s/(c.*)/[$1]/s; print;'

这个解决方案确实有更多的字符,但对于其他读者来说可能更容易理解(三个月后你将是;-D)

于 2012-12-18T19:47:09.157 回答
0

你一次读一行,那么你认为它怎么可能匹配跨越多行的东西?

添加-0777以将“行”重新定义为“文件”(不要忘记添加 /s 以.匹配换行符)。

$ (echo a b c d e; echo f g h i j; echo l m n o p) | perl -0777pe's/(c.*)/[$1]/s'
a b [c d e
f g h i j
l m n o p
]
于 2012-12-18T12:26:50.460 回答