用perl替换正则表达式EOL会产生意想不到的结果

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用perl替换正则表达式EOL会产生意想不到的结果相关的知识,希望对你有一定的参考价值。

为什么在第2行和第3行的开头有一个美元符号?

➜ echo -e "hello
world" | perl -pe 's/$/$/g'
hello$
$world$
$%

在上面,我试图在每一行的末尾添加一个美元符号,但不知何故它也在开头附加一个美元符号。启用全局标志时会执行此操作。但是当我删除全局标志时,它工作正常:

➜ echo -e "hello
world" | perl -pe 's/$/$/'
hello$
world$

任何人都可以解释发生了什么吗?也许它与' r n'字符有关?

编辑:添加lookbehind案例

在这种情况下,这不仅仅是打破,还有其他情况。考虑以下:

➜ echo -e "A
B
C
D" | perl -pe 's/(?<!A)$/$/'
A
$B$
C$
D$

上面,我想用$来标记不以“A”结尾的行。第2行的额外美元符号不应该在那里。我甚至没有使用全球旗帜。


解决方案:现在好了。第二个解决方案是这样的(有关解释,请参阅Wiktor Stribiżew's answer

➜ echo -e "A
B
C
D" | perl -pe 's/(?<!A|
)$/$/'
A
B$
C$
D$

但要注意,如果你尝试使用多个单个字符,它会抛出Variable length lookbehind not implemented in regex。例如:

➜ echo -e "AA
BB
CC
DD" | perl -pe 's/(?<!AA|
)$/$/'
Variable length lookbehind not implemented in regex m/(?<!AA|
)$/ at -e line 1.

要解决此问题,请在换行前添加适当数量的.

➜ echo -e "AA
BB
CC
DD" | perl -pe 's/(?<!AA|.
)$/$/'
AA
BB$
CC$
DD$
答案

关键是$是零宽度断言,它可以在最终换行符之前匹配。 Perl读取一条尾随 的行,所以$匹配两次:之前和之后。

你的字符串基本上是Perl的两行:

hello

world

并且$可以在最终换行符之前和字符串的最后匹配。因此,两行中都有两个匹配(在此上下文中为“字符串”)。

如果要匹配字符串的结尾,请使用z

perl -pe 's/z/$/g'

因为z只匹配字符串的最后一部分,但是不太可能有人想要使用它,因为它会在第二行和后续行的开头有效插入$,并将其添加为最后一行。

要仅在最后一个$之前插入 并停止,请使用你的perl -pe 's/$/$/',没有g修饰符。

另一答案

如果您确实希望将其与全局替换一起使用,则可以使用以下命令:

echo -e "hello
world" | perl -pe 's/^(.*)$/1$/g'                                                                                          
hello$
world$

或者没有反向引用,您可以使用:

echo -e "hello
world" | perl -pe 's/
$/$
/g'
hello$
world$

你可能需要用 替换 ,如果你从windows操作文件或只是使用dos2unix删除Windows EOL chars

以上是关于用perl替换正则表达式EOL会产生意想不到的结果的主要内容,如果未能解决你的问题,请参考以下文章

教你notepad++用正则表达式替换掉各行逗号前面内容

Perl 正则表达式替换,环境变量评估

Perl编程-6正则表达式--替换+转化

sed 和 Perl 正则表达式替换一次,带有多个替换标志

如何在 perl 正则表达式替换命令中使用 unicode 字符?

Perl 正则表达式变量替换打印 1 而不是所需的提取