8

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

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

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

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

4

4 回答 4

7

你有正确的想法,一个迷你状态机,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

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

于 2012-10-23T04:37:02.933 回答
3

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

$ sed -n '/^Hi/,/patterns/{s/^Hi //;/^patterns/d;p;}' file
I would like
to print text
between these
于 2012-10-23T04:36:53.747 回答
2

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

sed '/Hi /!d;s//\n/;s/.*\n//;ta;:a;s/patterns.*$//;tb;$!{n;ba};:b;/^$/d' file
于 2012-10-23T07:00:41.247 回答
1

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

$ awk 'sub(/^Hi /,""){f=1} /patterns/{f=0} f'  file
I would like
to print text
between these
于 2012-10-23T18:11:33.690 回答