【问题标题】:RegEx for capturing contents between asterisks, except for a wordRegEx 用于捕获星号之间的内容,单词除外
【发布时间】:2019-06-08 06:40:31
【问题描述】:

如果只能使用正则表达式,如何提取此字符串中除“NOT”之外的星号之间的文本?

* apple *  * orange tasty *  * banana *  * grape NOT *

预期结果:

apple

orange tasty

banana

【问题讨论】:

  • 负前瞻。谷歌这个。
  • PCRE 没问题。我想用 grep -Po 来提取。

标签: regex grep pcre regex-lookarounds regex-group


【解决方案1】:

您可以使用以下正则表达式: \*(\s*(?!NOT)\w+)+\s*\*

See explanation on regex101...

Here you can visualize your regular expression...

【讨论】:

    【解决方案2】:

    没有看完所有答案,但是Mr. Morton的答案很有见地。

    这个问题也很有趣,有多种方法可以解决,我们将从一个表达式开始,该表达式使用单词边界收集我们的 NOT 单词,并根据我们想要的输出进行更改。最后,我们从字符串的开头滑动到结尾可能剩下的内容,特别是如果我们希望替换,但最后一部分是不必要的:

    (?:(\bNOT\b).)*|([\w\s]+?)|(.*?)
    

    在这里,我们有两个不受欢迎的组:

    (?:(\bNOT\b).)*
    

    (.*?)
    

    我们想要的数据在第二个捕获组中:

    ([\w\s]+?)
    

    如果我们想要的字符比我们的 char 类中列出的字符多,可以简单地修改它:[\w\s]

    正则表达式

    如果不需要此表达式并且您希望对其进行修改,请访问此链接regex101.com

    正则表达式电路

    jex.im 可视化正则表达式:

    Demo

    【讨论】:

      【解决方案3】:

      您也可以使用它来提取另一个组中的其他数据:

      \*\s?(?:([a-zA-Z0-9 ]+?NOT))\s?\*|\*\s?([a-zA-Z0-9 ]+?)\s?\*
      

      这也适用于其他正则表达式引擎。 看看here
      视觉Embeded

      <iframe frameborder="0" width="746" height="562" src="https://jex.im/regulex/#!embed=true&flags=&re=%5C*%5Cs%3F(%3F%3A(%5Ba-zA-Z0-9%20%5D%2B%3FNOT))%5Cs%3F%5C*%7C%5C*%5Cs%3F(%5Ba-zA-Z0-9%20%5D%2B%3F)%5Cs%3F%5C*"></iframe>

      【讨论】:

        【解决方案4】:

        您可以使用 SKIP FAIL 和 \K 忘记当前匹配的内容:

        \*[^*]* NOT [^*]*\*(*SKIP)(*FAIL)|\*\s*\K\w+(?: \w+)*(?= \*)
        

        说明

        • \*[^*]* NOT [^*]*\* 使用否定字符类在星号和空格之间不匹配
        • (*SKIP)(*FAIL) 跳过匹配项
        • |或者
        • \*\s*\K 匹配 asterix,0+ 个空白字符并忘记匹配的内容
        • \w+(?: \w+)* 匹配 1+ 单词字符和重复模式以匹配空格和 1+ 单词字符
        • (?= \*) 正向前瞻,断言右边是一个空格和一个星号

        Regex demo | grep demo

        例如:

        echo "* apple * * orange tasty * * banana * * grape NOT *" | grep -Po "\*[^*]* NOT [^*]*\*(*SKIP)(*FAIL)|\*\s*\K\w+(?: \w+)*(?= \*)"
        

        结果

        apple
        orange tasty
        banana
        

        【讨论】:

          【解决方案5】:

          Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

          使用 GNU awk 进行多字符 RS 和 RT:

          $ awk -v RS='[*][^*]+[*]' 'RT !~ /NOT/{print RT}' file
          * apple *
          * orange tasty *
          * banana *
          

          在每个 UNIX 机器上的任何 shell 中使用任何 awk:

          $ awk '{ while ( match($0,/[*][^*]+[*]/) ) {str=substr($0,RSTART,RLENGTH); if (str !~ /NOT/) print str; $0=substr($0,RSTART+RLENGTH)} }' file
          * apple *
          * orange tasty *
          * banana *
          

          上面用几个微不足道的正则表达式而不是一个复杂的正则表达式解决了这个问题。在输出的每一端删除 *s 是微不足道的,但我觉得 OP 会想要使用一些复杂的单个正则表达式。

          【讨论】:

            猜你喜欢
            • 2017-06-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-07-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多