代码之家  ›  专栏  ›  技术社区  ›  mon

sed-为什么“[.]”与一行的开头和结尾匹配?

  •  1
  • mon  · 技术社区  · 1 年前

    为什么一行的开头和结尾由匹配 [.]* 以及如何避免?

    这个模式似乎与单词边界匹配,但不确定它是否如设计的那样,以及它实现了哪个规范。

    $ echo " a " | sed -n 's/[.]*/X/pg'
    X XaX X
    
    $ echo " a " | sed -n 's/[\b]*/X/pg'
    X XaX X
    
    0 回复  |  直到 1 年前
        1
  •  2
  •   jhnc    1 年前

    请注意 \b 括号内没有特殊含义。这只是一个字符列表。

    [.]* [\b]* 火柴 或括号中的多个字符。

    因此,它们匹配一个或多个字符的任何运行,其中紧接在字符运行之前和之后的空字符串只是该运行的一部分。

    它们还匹配并没有紧跟在字符序列前面或后面的任何空字符串。


    将空间替换为更可见的内容,您的输入是: sas

    没有任何字符 . , \ 也没有 b 出现在字符串中。因此,没有长度为1或更长的跑步。有了这个输入 [.]* b 相当于“匹配空字符串”。

    • 第行开始和第一行之间的空字符串 s 比赛
    • 第一个之间的空字符串 s a 比赛
    • 之间的空字符串 和第二 s 比赛
    • 秒之间的空字符串 s 和行尾匹配

    这4场比赛解释了 X s添加到您的示例输出中。


    使用 b 意思是单词边界不是标准的,尽管的某些版本 sed 接受它(或相关的 \< \> ).

    不使用此扩展更安全,当然也不使用 * .

    的偶数版本 sed 似乎支持它的结果不直观且不一致。

    例如,使用GNU sed 4.8:

    $ echo ,aa, | sed 's/\b/x/g'
    ,xaax,
    $ echo ,aa, | sed 's/\b*/x/g'
    ,aa,
    $ echo ,aa, | sed 's/\b\{1,\}/x/g'
    sed: -e expression #1, char 14: Invalid preceding regular expression
    $ echo ,aa, | sed 's/\(\b\)\{1,\}/x/g'
    ,xaax,
    

    对于忙碌箱sed 1.30.1:

    $ echo ,aa, | busybox sed 's/\b/x/g'
    ,xaxa,
    $ echo ,aa, | busybox sed 's/\b*/x/g'
    ,aa,
    $ echo ,aa, | busybox sed 's/\b\{1,\}/x/g'
    sed: bad regex '\b\{1,\}': Invalid preceding regular expression
    $ echo ,aa, | busybox sed 's/\(\b\)\{1,\}/x/g'
    ,xaxa,
    

    甚至像Perl这样的其他程序也需要小心:

    $ echo ,aa, | perl -ple 's/\b/x/g'
    ,xaax,
    $ echo ,aa, | perl -ple 's/\b*/x/g'
    x,xaxax,x
    $ echo ,aa, | perl -ple 's/\b{1,}/x/g'
    '1,' is an unknown bound type in regex; marked by <-- HERE in m/\b{1, <-- HERE }/ at -e line 1.
    $ echo ,aa, | perl -ple 's/(\b){1,}/x/g'
    ,xaax,
    $ echo ,aa, | perl -ple 's/\b+/x/g'
    ,xaax,