为什么`perl -pe的/ $ / \ n / g'`添加2个空白行?

时间:2018-02-08 12:54:42

标签: regex perl

我正在阅读一本班轮书并且遇到了

perl -pe 's/$/\n/' file

在每行之后插入一个空白行,方法是将行的结尾设置为新行,从而在现有换行符中添加一个新行,从而产生一个空行。 由于这是模式末尾没有g的第一个示例,我尝试了

perl -pe 's/$/\n/g' file

这导致行之间有2个空白行 我原本预计没有区别,因为每行只有一个$所以更换所有这些应该与更换第一个相同。
这是怎么回事?

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中的任何一个

如果仍然存在问题,请再次询问。我打算写一些关于零宽度的比赛,但很难知道如果没有它我的回答是否清楚