【问题标题】:awk concatenate strings till contain substringawk 连接字符串直到包含子字符串
【发布时间】:2018-05-27 12:44:44
【问题描述】:

我有一个来自this 示例的awk 脚本:

awk '/START/{if (x) print x; x="";}{x=(!x)?$0:x","$0;}END{print x;}' file

这是一个带行的示例文件:

$ cat file
START
1
2
3
4
5
end
6
7
START
1
2
3
end
5
6
7

所以当目标字符串包含end 字时,我需要停止连接,因此所需的输出是:

START,1,2,3,4,5,end
START,1,2,3,end

【问题讨论】:

  • 您的问题不包含问题。
  • 尽管如此,5 个用户给了我一个答案。所以,如果它不包含问号,对大多数人来说似乎是可以的。

标签: regex bash awk


【解决方案1】:

你可以使用这个awk:

awk '/START/{p=1; x=""} p{x = x (x=="" ? "" : ",") $0} /end/{if (x) print x; p=0}' file

START,1,2,3,4,5,end
START,1,2,3,end

【讨论】:

    【解决方案2】:

    短Awk解决方案(虽然它会检查/end/模式两次):

    awk '/START/,/end/{ printf "%s%s",$0,(/^end/? ORS:",") }' file
    

    输出:

    START,1,2,3,4,5,end
    START,1,2,3,end
    

    • /START/,/end/ - 范围模式

    范围模式由两个用逗号分隔的模式组成,在 形成‘begpat, endpat’。它用于匹配连续的范围 输入记录。第一个模式begpat 控制范围的位置 开始,而endpat 控制模式结束的位置。

    • /^end/? ORS:"," - 为范围内的当前项目设置分隔符

    【讨论】:

    • 永远不要使用范围表达式,因为它们会使琐碎的脚本变得非常简短,或者当需求变得更有趣时需要完全重写或重复条件(例如,在这种情况下测试“end”两次)。始终使用标志变量,例如stackoverflow.com/a/47796423/1745001
    • @EdMorton,是的,我意识到它会检查/end/ 模式两次。除了基于“标志”的方法之外,让它只是一种替代方法。我不会将我建议的方法称为唯一最好的方法......其他答案已经足够好了
    【解决方案3】:

    这是另一个awk

    $ awk '/START/{ORS=","} /end/ && ORS=RS; ORS!=RS' file
    
    START,1,2,3,4,5,end
    START,1,2,3,end
    

    请注意,/end/ && ORS=RS; 是 /end/{ORS=RS; print} 的缩写形式

    【讨论】:

      【解决方案4】:

      另一种方式,类似于How to select lines between two patterns?中的答案

      $ awk '/START/{ORS=","; f=1} /end/{ORS=RS; print; f=0} f' ip.txt
      START,1,2,3,4,5,end
      START,1,2,3,end
      
      • 这不需要缓冲区,但不检查START 是否有对应的end
      • /START/{ORS=","; f=1} 将 ORS 设置为 , 并设置一个标志(控制要打印的行)
      • /end/{ORS=RS; print; f=0} 在结束条件下将 ORS 设置为换行符。打印该行并清除标志
      • f只要设置了这个标志就打印输入记录

      【讨论】:

        【解决方案5】:

        由于我们似乎已经找到了实现此目的的方法,因此这是一个相当合理的方法,使用 GNU awk 处理多字符 RS、RT 和 gensub():

        $ awk -v RS='end' -v OFS=',' 'RT{$0=gensub(/.*(START)/,"\\1",1); $NF=$NF OFS RT; print}' file
        START,1,2,3,4,5,end
        START,1,2,3,end
        

        【讨论】:

          猜你喜欢
          • 2013-08-18
          • 1970-01-01
          • 2013-12-07
          • 2013-08-06
          • 1970-01-01
          • 1970-01-01
          • 2017-12-29
          • 1970-01-01
          • 2014-05-04
          相关资源
          最近更新 更多