【问题标题】:sed/awk - print text between patterns spanned across multiple linessed/awk - 在跨越多行的模式之间打印文本
【发布时间】:2012-10-23 04:30:27
【问题描述】:

我是脚本新手,正在尝试学习如何提取存在于两种不同模式之间的任何文本。但是,我仍然无法弄清楚如何在以下场景中提取两种模式之间的文本:

如果我有我的输入文件阅读:

Hi I would like
to print text
between these 
patterns

而我预期的输出如下:

I would like
to print text
between these 

即我的第一个搜索模式是“Hi”并跳过此模式,但打印匹配模式之后存在于同一行中的所有内容。我的第二个搜索模式是“模式”,我想完全避免打印此行或除此之外的任何行.

我尝试了以下方法:

sed -n '/Hi/,/patterns/p' test.txt 

[输出]

Hi I would like
to print text
between these 
patterns 

接下来,我尝试了:

`awk ' /'"Hi"'/ {flag=1;next} /'"pattern"'/{flag=0} flag { print }'` test.txt 

[输出]

to print text
between these

有人可以帮助我确定如何实现这一目标吗? 提前致谢

【问题讨论】:

    标签: bash sed awk


    【解决方案1】:

    您的想法是正确的,awk 中的迷你状态机,但您需要根据以下脚本进行一些轻微的修改:

    pax> echo 'Hi I would like
    to print text
    between these 
    patterns ' | awk '
        /patterns/ { echo = 0 }
        /Hi /      { gsub("^.*Hi ", "", $0); echo = 1 }
                   { if (echo == 1) { print } }'
    

    或者,压缩形式:

    awk '/patterns/{e=0}/Hi /{gsub("^.*Hi ","",$0);e=1}{if(e==1){print}}'
    

    输出是:

    I would like
    to print text
    between these 
    

    根据要求。

    其工作方式如下。 echo 变量最初是 0,这意味着不会发生回显。

    依次检查每一行。如果它包含patterns,则禁用回显。

    如果它包含Hi 后跟一个空格,则启用回显并且 gsub 用于修改该行以删除直到Hi 的所有内容。

    然后,无论如何,当echo 标志打开时,该行(可能已修改)会被回显。

    现在,将会出现以下极端情况:

    • 包含两次出现的Hi 的行;或
    • patterns 之前包含某些内容的行。

    你还没有指定应该如何处理,所以我没有打扰,但基本概念应该是相同的。

    【讨论】:

    • 非常感谢您的解答和详细说明 paxdiablo,您的解决方案。奇迹般有效 :-)。就我而言,我没有在同一行重复出现模式单词,也没有在“模式”之前出现任何单词。在我的场景中,我总是可以识别出我想丢弃所有内容的行,并且该行总是以相同的模式开始。再次感谢您的回复,非常感谢:-)
    • 几个问题:1) "^.*Hi" 与 RE 中的 "Hi" 相同,2) 您不需要将 $0 指定为 *sub() 的第三个参数, 3) 当你只想替换 1 次出现时,你不需要 gsub(),并且 4) "{ if (echo == 1) { print } }" 就相当于只是 "echo"。
    • 编辑。 Re 1,不,不是,不是在你替换时 - 区别在于只替换 hi 或线上的所有内容,包括 hi。其他观点是有效的,但主要是风格上的。
    【解决方案2】:

    更新解决方案以删除“模式”行:

    $ sed -n '/^Hi/,/patterns/{s/^Hi //;/^patterns/d;p;}' file
    I would like
    to print text
    between these
    

    【讨论】:

      【解决方案3】:

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

      sed '/Hi /!d;s//\n/;s/.*\n//;ta;:a;s/patterns.*$//;tb;$!{n;ba};:b;/^$/d' file
      

      【讨论】:

        【解决方案4】:

        在行首 find+replace Hi 时设置一个标志 (f),找到模式时清除它,然后在设置标志时调用默认打印:

        $ awk 'sub(/^Hi /,""){f=1} /patterns/{f=0} f'  file
        I would like
        to print text
        between these
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-01-04
          • 2013-06-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-12
          • 1970-01-01
          相关资源
          最近更新 更多