【问题标题】:merging lines based on pattern基于模式合并线
【发布时间】:2015-08-05 05:27:15
【问题描述】:

您能否建议一个 sed/awk 命令来合并文件中以模式开头并以括号结尾的行?匹配是可变的行号并由右括号控制。

例如对于以下输入,提取模式以pattern1为开头并以'}'结尾

blah blah
pattern1 {
blah blah 1
blah blah 2
blah blah 3
}
pattern1 {
blah blah 1
blah blah 2
}

预期的输出是

blah blah 
partern1 {blah blah 1 blah blah 2 blah blah 3}
partern1 {blah blah 1 blah blah 2}

【问题讨论】:

    标签: regex awk sed


    【解决方案1】:

    这解决了你在 awk 中的问题,方法是记录我们是否处于模式的中间,并对其采取行动。鉴于您的输入文件名为 input.txt:

    awk '/{/ {
        inPattern=1
    }
    {
        if (inPattern) {
            # When in a pattern, print the line (because of printf, this is without the newline).
            printf "%s ",$0;
        } else {
            # Otherwise, just print the line.
            print;
        }
    }
    /}/ {
        inPattern=0
    
        # Do this to go to a new line.
        print ""
    }' input.txt
    

    祝你好运!

    【讨论】:

      【解决方案2】:

      使用 GNU sed:

      $ sed '/pattern1/ {:x; N; s/\n/ /; /}/! bx}' infile
      blah blah
      pattern1 { blah blah 1 blah blah 2 blah blah 3 }
      pattern1 { blah blah 1 blah blah 2 }
      

      解释:

      /pattern1/ {    # Line matches pattern1
          :x          # Label to branch to
          N           # Add next line to pattern space
          s/\n/ /     # Replace newline with space
          /}/! bx     # If pattern space doesn't contain '}', branch to :x
      }               # End of cycle: print pattern space
      

      如果你想用变量替换pattern1,你必须用不同的方式引用:

      $ var=pattern1
      $ sed "/$var/ {:x; N; s/\n/ /; /}/! bx}" infile
      

      【讨论】:

      • 这对我在 OSX 或 FreeBSD 中使用不起作用。您可能在使用 GNU sed 吗?如果是这样,最好在您的答案中指定这一点,以便读者知道您的答案不可移植。
      • @ghoti 是的,我正在使用 GNU sed。让我看看我是否可以让它便携。
      • @ghoti 话虽这么说,但它对我使用 --posix 标志有效。什么不适合你?
      • sed: 1: "/pattern1/ {:x; N; s/\n ...": unexpected EOF (pending }'s) 是我在 FreeBSD 和 OSX 中看到的错误。起初我认为问题可能是您使用了\n,它也不是可移植的,但是当我尝试运行sed -e $'/pattern1/ {; :x; N; s/\\\n/ /; /}/! bx;}' file(带有额外的行分隔符)时,我得到了错误sed: 2: "/pattern1/ {; :x; N; s/ ...": invalid command code ;。我现在有更多的时间来调试,所以..祝你好运。 :)
      • @ghoti 也许是未转义的}。不确定我是否可以在不访问 FreeBSD/OSX sed 的情况下正确调试它。不过,我会阅读便携式 sed :) 哦,\n 不是便携式的? FreeBDS/OSX sed 不符合 POSIX 标准吗? spec 表示支持 \n
      【解决方案3】:

      这是一个可移植的 sed 解决方案(适用于 GNU sed、OSX、FreeBSD 等),尽管它适用于所有模式,而不仅仅是匹配 /pattern1/ 的部分。:

      sed -ne '/{/{;x;/}/d;p;x;h;d;}; /}/! {;H;d;}; /}/{;H;x;s/\n/ /g;};p' file
      

      为了便于阅读,脚本如下所示:

      • /{/{; - 对于包含左括号 ({) 的任何行...
        • x;/}/d;p;x;h;d;}; - 打印它.. 除非它是一个右大括号,然后将它添加到我们的保留中。
      • /}/! {;H;d;}; - 对于没有右括号的任何行,将其附加到我们的保留中。
      • /}/{;H;x;s/\n/ /g;}; - 对于任何带右大括号的行,追加它,交换保持和模式空格,并用换行符替换空格。
      • p - 并打印结果(因为我们有一个 -n 作为 sed 选项)。

      适用于您的测试输入数据,我没有在变体上测试它。

      请注意,如果模式中嵌入了模式,这肯定会失败。要处理这种情况,您需要使用实际的语言,例如,它可以在遍历文件时跟踪嵌套级别。

      【讨论】:

        猜你喜欢
        • 2019-11-08
        • 1970-01-01
        • 2016-12-02
        • 2016-01-02
        • 2019-03-12
        • 2017-08-31
        • 1970-01-01
        • 2016-10-21
        相关资源
        最近更新 更多