【问题标题】:sed split substring that may or may not be presentsed 拆分子字符串可能存在也可能不存在
【发布时间】:2022-01-05 11:29:52
【问题描述】:

尝试根据可能存在或不存在的文本拆分文本列。

示例文件:

TEXT1D1NEWBWP210HTEXT2
TEXT1D1BWP210HTEXT2

预期输出:

TEXT1D1NEWBWP210HTEXT2 NEWBWP 210H
TEXT1D1BWP210HTEXT2 BWP 210H

cmd used --- 期待那个“?”将检查子字符串“NEW”是否存在并打印以防万一。

cat <text_file> | sed -e 's/.*\(\s*\)\(NEW\)\?\(BWP\)\([0-9]\+\)H.*/\0 \2\3 \4H/'

上述cmd的输出是

TEXT1D1NEWBWP210HTEXT2 BWP 210H
TEXT1D1BWP210HTEXT2 BWP 210H

不知道我在这里做错了什么...... :)

【问题讨论】:

    标签: sed


    【解决方案1】:

    使用sed

    $ sed 's/\(\(NEW\)\?BWP\)\([^A-Z]*.\).*/& \1 \3/' input_file
    TEXT1D1NEWBWP210HTEXT2 NEWBWP 210H
    TEXT1D1BWP210HTEXT2 BWP 210H
    

    【讨论】:

    • 因为\([0-9]\+\)H 我假设210H 不是固定字符串。
    【解决方案2】:

    我在这里做错了什么

    呃,这将很难,并且与正则表达式的工作方式密切相关。正则表达式从左到右匹配。它匹配贪婪 - 匹配所有内容,直到无法匹配为止。然后它返回并匹配字符串“从头开始”。因为它从末尾匹配 ~BWP,所以 NEW 永远不会出现。

    .*\(\s*\)\(NEW\)\?\(BWP\)\([0-9]\+\)H.*
                                             Events:
    ^^                                       - matches everything
        ^^^                                  - matches nothing (end of string)
              ^^^^^^^^                       - matches nothing (end of string)
                        ^^^                  - engine is at the end of string
                                               so it goes back until BWP is matched
    ^^                                       - matches 'TEXT1D1NEWBWP210HTEXT' (from the back)
                        ^^^                  - does not match
    ^^                                       - matches 'TEXT1D1NEWBWP210HTEX' (from the back)
                        ^^^                  - does not match
    ^^                  ^^^                  - ^^^ etc. for each character from the end
    ^^                                       - matches 'TEXT1D1NEWB' (from the back)
                        ^^^                  - does not match
    ^^                                       - matches 'TEXT1D1NEW' (from the back)
                        ^^^                  - matches 'BWP'
                            ^^^..            - regex engine continues
    

    您可以在https://www.regular-expressions.info/repeat.html#lazy 阅读更多内容。

    无论如何,您必须对其进行编程:

     $ sed -e '
        s/.*\s*\(NEWBWP\)\([0-9]\+H\).*/\0 \1 \2/;
        t a;  # if the above s was successful, go to a
           s/.*\s*\(BWP\)\([0-9]\+H\).*/\0 \1 \2/;
        : a;
       ' <<<$'TEXT1D1NEWBWP210HTEXT2\nTEXT1D1BWP210HTEXT2'
     TEXT1D1NEWBWP210HTEXT2 NEWBWP 210H
     TEXT1D1BWP210HTEXT2 BWP 210H
    

    【讨论】:

      【解决方案3】:

      这可能对你有用(GNU sed):

      sed -E 's/(NEWBWP|BWP)([0-9]+H).*/& \1 \2/' file
      

      交替|从左到右工作,因此如果NEWBWP不匹配,则将尝试BWP

      【讨论】:

        【解决方案4】:

        将 GNU 或 BSD sed 用于 -E,因此您不需要所有这些反斜杠(您已经使用 GNU sed 来处理 \s):

        $ sed -Ee 's/((NEW)?BWP)([0-9]+)H.*/& \1 \3H/' file
        TEXT1D1NEWBWP210HTEXT2 NEWBWP 210H
        TEXT1D1BWP210HTEXT2 BWP 210H
        

        您的正则表达式的主要问题是初始 .* 会消耗可选的 NEW(如果存在)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-01
          • 1970-01-01
          • 2017-08-04
          • 1970-01-01
          • 2020-06-03
          相关资源
          最近更新 更多