【问题标题】:Delimiter that may / may not span multiple lines using sed使用 sed 可能/可能不会跨越多行的分隔符
【发布时间】:2018-11-02 16:34:34
【问题描述】:

我有一个实用程序预先生成的配置文件。如何提取由'), 分隔且可能跨多行的参数字符串?

FILE1 可以看起来像这样 - PARM3 跨越多行:

OPERAND      ID          = 'XXXX',
             ....
             PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n'),
             PARM4       = ( 'VALUE4',
                              ....
                             'VALUE4n'),
                              ....

FILE2 可以如下所示 - PARM3 不跨越多行:

OPERAND      ID          = 'XXXX',
             ....
             PARM3       = ( 'VALUE3A'),
             PARM4       = ( 'VALUE4',
                              ....
                              'VALUE4n'),
             ....

对于FILE1,如果分隔符'), 在另一行,则提取很好

sed -n "/.* PARM3 .*/,/')\,/p" FILE1

输出:

  PARM3       = ( 'VALUE3A',
                  ....
                  'VALUE3n'),

对于FILE2,如果分隔符'), 在同一行,则提取不起作用

sed -n "/.* PARM3 .*/,/')\,/p" FILE2

输出:

        PARM3       = ( 'VALUE3A'),
        PARM4       = ( 'VALUE4',
                         ....
                        'VALUE4n'),

我怎样才能修复这个 sed 语句,只使用 sed 来处理可能在也可能不在同一行的分隔符?

【问题讨论】:

  • 将 PARM3 后的 .* 更改为 .*?
  • @Matt.G Sed 不支持非贪婪匹配。
  • 你可以在 sed 中使用分支。如果在同一行中找到),如果不继续地址范围,则跳转。

标签: regex awk sed


【解决方案1】:

如果您有 GNU grep,则可以使用其 -z 选项将完整的输入视为一行:

$ grep -Ezo '\s+PARM3\s+=\s+\([^)]*\)' FILE2

             PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n')

-o 只保留匹配项,-E 启用扩展正则表达式。

正则表达式搜索PARM3 =,由任意数量的空格包围,然后是(,然后是直到并包括结束)的所有内容。为了避免贪婪匹配,我使用[^)](“不是右括号”)。

如果您不需要前导空格,可以跳过它们,如果您需要尾随逗号,可以添加(可选,以防它不存在):

$ grep -Ezo 'PARM3\s+=\s+\([^)]*\),?' infile
PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n'),

或获得正确的对齐,但不是匹配前的换行符:

$ grep -Ezo '[[:blank:]]*PARM3\s+=\s+\([^)]*\),?' infile
             PARM3       = ( 'VALUE3A',
                              ....
                             'VALUE3n'),

【讨论】:

    【解决方案2】:

    [编辑]更简单:

    sed -n '/PARM3/,/)/{p;/)/q}' file
    

    sed 的一种方式:

    sed -n '/PARM3/{:a;/)/{p;q};N;ba}' file
    

    详情:

    /PARM3/ {     # if PARM3 is found
        :a            # define a label "a"
        /)/ {         # if ) is found
            p             # print the pattern space
            q             # quit
        }
        N             # append the next line to the pattern space
        ba            # go to label a
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用这个使用自定义RSgnu-awk 命令:

      awk -v RS='[[:blank:]]*PARM3[[:blank:]]*=[[:blank:]]*\\([^)]*\\),[[:blank:]]*' 'RT{print RT}' file
      

      对于 file1,它给出:

           PARM3       = ( 'VALUE3A',
                            ....
                           'VALUE3n'),
      

      对于 file2 它给出:

          PARM3       = ( 'VALUE3A'),
      

      【讨论】:

        猜你喜欢
        • 2010-09-23
        • 1970-01-01
        • 1970-01-01
        • 2019-09-17
        • 1970-01-01
        • 2022-11-13
        • 2022-01-05
        • 1970-01-01
        • 2015-09-20
        相关资源
        最近更新 更多