我正在尝试研究如何使用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调用标志?
答案 0 :(得分:10)
-p
逐行循环输入,其中“lines”由输入记录分隔符$/
分隔,输入记录分隔符默认为换行符。如果您想将所有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
]
有关这两个标志的信息,请参阅Command Switches in perlrun。 -l
(破折号)也很有用。
答案 1 :(得分: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;
答案 2 :(得分:1)
实际上你的单行看起来像这样:
while (<>) {
$ =~ s/(c.*)/[$1]/s;
}
这意味着正则表达式仅适用于输入的第一行。
答案 3 :(得分: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)
答案 4 :(得分:0)
你一次读一行,所以你怎么认为它可能匹配跨越多行的东西?
添加-0777
以将“line”重新定义为“file”(并且不要忘记添加/ 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
]