【问题标题】:How to regex-pattern-match a variable-length word with a fixed prefix?如何正则表达式匹配具有固定前缀的可变长度单词?
【发布时间】:2019-11-25 13:05:33
【问题描述】:

总结

一个正则表达式如何匹配我认为可能(?)最好描述为“具有固定前缀的可变长度单词”的内容?

详情

以下示例尝试删除aa:22。它们都不起作用。

所有命令的首选输出是bb:33 cc:44。当然,这些命令并非旨在删除前导或多余的空格。

我使用perl -pe(在第一个命令中未成功)尝试使可变长度模式匹配成为“非贪婪”。

在这些示例中,aa: 是前缀(可以认为是键值对中的“键”),22 是可变内容、可变长度值;即,它可能是aa:2vED/3rD@&x3J{ZB334}A(在此语法中,任何包含: 以外的非空白字符的字符串),但它总是以空白为边界(空格和制表符是唯一的空白字符,是的?) 或行尾。

进一步:可以以任何顺序找到单词序列(键值对)。因此,基于awk 的固定列匹配可能不起作用。

我正在寻找一个优雅、简单的解决方案。我已经阅读了许多 Stack Overflow 的答案,它们的正则表达式看起来非常冗长和复杂,以至于难以理解。显然我没有接受足够的正则表达式教育。

sed、perl、awk、grep 或任何其他面向 POSIX 的解决方案都是可以接受的,只要该解决方案与基线 macOS 和 Linux 兼容。

$ echo 'aa:22 bb:33 cc:44' | perl -pe 's|aa:.*\b||'

$ 
$ echo 'aa:22 bb:33 cc:44' | perl -pe 's|aa:.*?\b||'
22 bb:33 cc:44
$ 
$ echo 'aa:22 bb:33 cc:44' | perl -pe 's|aa:\B*\b||'
22 bb:33 cc:44
$ 
$ echo 'aa:22 bb:33 cc:44' | perl -pe 's|aa\B*\b||'
:22 bb:33 cc:44
$ 
$ echo 'aa:22 bb:33 cc:44' | perl -pe 's|aa:(?!.*)\b||'
aa:22 bb:33 cc:44
$ 
$ echo 'aa:22 bb:33 cc:44' | perl -pe 's|aa:(?!.*)*\b||'
22 bb:33 cc:44
$ 
$ echo 'aa:22 bb:33 cc:44' | perl -pe 's|aa:.*^(?!.*)||'
aa:22 bb:33 cc:44
$ 
$ echo 'reordering...'
reordering...
$ 
$ echo 'bb:33 aa:22 cc:44' | perl -pe 's|aa\B*\b||'
bb:33 :22 cc:44
$ 
$ 
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G1012
$ 

【问题讨论】:

    标签: regex sed key-value


    【解决方案1】:
    $ echo 'aa:22 bb:33 cc:44' | sed -E 's/aa:[^[:space:]:]*([[:space:]]|$)//'
    bb:33 cc:44
    $ echo 'bb:33 aa:22 cc:44' | sed -E 's/aa:[^[:space:]:]*([[:space:]]|$)//'
    bb:33 cc:44
    $ echo 'bb:33 cc:44 aa:22' | sed -E 's/aa:[^[:space:]:]*([[:space:]]|$)//'
    bb:33 cc:44
    
    • -E 用于 ERE 支持,
    • [^[:space:]:]* 匹配 0+ 除 wspace 和冒号以外的任何字符,
    • ([[:space:]]|$) 匹配边界 wspace 或 EOL。

    【讨论】:

    • 需要( |$)吗?
    • @PJProudhon 不是吗?
    • 非常感谢@oguzismail。以下推导(\s 替换 [:space:])似乎适用于所有这些示例:sed -E 's/aa:[^\s:]*(\s|$)//' 它是否普遍适用?
    • @JohnnyUtahh 我不能说是。 -E 和 \s 都不是可移植的。大多数 seds 都有 -E 但不能对 \s 说同样的话。如果您想要最大的便携性,请使用sed 's/aa:[^[:space:]:]*\([[:space:]]\|$\)//';它应该适用于所有符合 POSIX 的 seds
    • @JohnnyUtahh \s 和其他此类字符集在字符类中不起作用..它将匹配 \s 而不是空格...例如,echo 'a\sb\cdsssssssssss12' | sed 's/[\s]*//g' 将给abcd12
    【解决方案2】:

    这可能有效:

    echo 'aa:22 bb:33 cc:44' | sed -r 's/aa:[^ ]+ //g'
    bb:33 cc:44
    

    它会查找 aa 和所有其他字符,直到第一个空格。

    【讨论】:

    • 在这种情况下不起作用:$ echo 'bb:33 cc:44 aa:22' | sed -r 's/aa:[^ ]+ //g' --> bb:33 cc:44 aa:22。删除最后一个空格,它可以工作......但在aa:22 不在行尾的情况下会留下额外的“双空格”。有办法解决吗?
    • 另外,对于[^ ](仅限空格),这可能不适用于制表符分隔的字符串。
    猜你喜欢
    • 2012-02-21
    • 1970-01-01
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 2012-02-21
    相关资源
    最近更新 更多