我正在阅读一本班轮书并且遇到了
perl -pe 's/$/\n/' file
在每行之后插入一个空白行,方法是将行的结尾设置为新行,从而在现有换行符中添加一个新行,从而产生一个空行。
由于这是模式末尾没有g
的第一个示例,我尝试了
perl -pe 's/$/\n/g' file
这导致行之间有2个空白行
我原本预计没有区别,因为每行只有一个$
所以更换所有这些应该与更换第一个相同。
这是怎么回事?
答案 0 :(得分:9)
/$/
匹配“字符串结尾”。这可能是
/\z/
),/(?=\n\z)/
)。(此外,/$/m
与“行尾”匹配。这可能是
/(?=\n)/
)。)。
使用替换/$/\n/g
,正则表达式匹配两次:在换行符之前一次,然后在字符串末尾再次匹配:
第一场比赛在换行前:
"foo\n"
# ^ match
在当前比赛结束前放置换行符:
"foo\n\n"
# ^ insert before
下一场比赛是在字符串的末尾:
"foo\n\n"
# ^ match
在当前比赛结束前插入换行符:
"foo\n\n\n"
# ^ insert before
未找到进一步匹配。
解决方案:如果$
适用于DWIMmy,请始终明确地与\z
或\n
匹配,可能与(?=\n)
等前瞻相匹配。请考虑匹配所有Unicode行分隔符\R
,而不仅仅是\n
。
答案 1 :(得分:2)
这并不是对情况的充分理解。 $
是一个定义严重且不直观的元字符
零宽度匹配
它会在绑定字符串末尾的换行符之前匹配
它将匹配绑定字符串末尾的
使用/m
修饰符,它也会在任何换行符之前匹配,但不会紧跟在它之后,除非它是字符串的最后一个字符< / p>
\z
更有用:它只在字符串
&#34;将行尾设置为新行&#34;
提及&#34;线&#34;完全是误导性的,你应该小心地在评论中解释你正在应用的含义。如果你有
my $s = "xxx\n"
然后
say pos($s) while $s =~ /$/g
将产生
3
4
即。 之前的和之前的,因为它恰好位于字符串的末尾
这也是为什么你的s/$/\n/g
增加了两个新行:对于/$/
之内这个字符串两个零宽度匹配,并且全局替换发现他们并且以换行符替换它们两者,从而导致三个换行而不是原来的
目前还不清楚你的意图
在字符串末尾添加换行符,无论有哪些内容s/\z/\n/
或$s .= "\n"
如果你想确保,比如说,有一个字符串的结束正好两个新行,那么就先删除任何现有的换行符与s/\n+\z/\b\n/
如您所见,\z
比$
如果您正在处理跨平台数据,请不要忘记\R
。它将匹配任何标准行终止符:CR,LF或CRLF中的任何一个
如果仍然存在问题,请再次询问。我打算写一些关于零宽度的比赛,但很难知道如果没有它我的回答是否清楚