如何在两个标记模式之间选择可能会用awk / sed多次出现的行


119

使用awksed如何选择出现在两个不同标记图案之间的线?可能会有多个部分标有这些模式。

例如:假设文件包含:

abc
def1
ghi1
jkl1
mno
abc
def2
ghi2
jkl2
mno
pqr
stu

起始模式为abc,结束模式为,mno 所以我需要输出为:

def1
ghi1
jkl1
def2
ghi2
jkl2

我使用sed一次匹配模式:

sed -e '1,/abc/d' -e '/mno/,$d' <FILE>

有什么办法sedawk 重复做直到文件结束?

Answers:


188

awk在必要时与标志一起使用以触​​发打印:

$ awk '/abc/{flag=1;next}/mno/{flag=0}flag' file
def1
ghi1
jkl1
def2
ghi2
jkl2

这是如何运作的?

  • /abc/匹配具有此文本的行,也是/mno/如此。
  • /abc/{flag=1;next}设置flag何时abc找到文本。然后,它跳过了这一行。
  • /mno/{flag=0}找到flag文字时取消设置mno
  • 最后flag是具有默认操作的模式,即print $0:如果flag等于1,则打印该行。

有关更详细的描述和示例,以及显示或不显示图案的情况,请参见如何在两个图案之间选择线?


30
如果要打印介于图案之间(包括图案)的所有内容,则可以使用 awk '/abc/{a=1}/mno/{print;a=0}a' file
scai

6
是的,@ scai!甚至awk '/abc/{a=1} a; /mno/{a=0}' file-在此a条件下,在set 之前将条件置于/mno/true 之前,将其评估为true(并打印)a=0。这样我们就可以避免写作print
fedorqui'SO停止伤害

12
@scai @fedorqui对于包括模式输出,您可以执行awk '/abc/,/mno/' file
Jotne 2013年

1
@hkasera awk '/abc/{flag=1}/mno/{flag=0}flag' file应该使。
fedorqui'SO停止伤害

2
@EirNym是一个很奇怪的场景,可以用非常不同的方式处理:您要打印哪些行?可能awk 'flag; /PAT1/{flag=1; next} /PAT1/{flag=0}' file会。
fedorqui'SO停止伤害

45

使用sed

sed -n -e '/^abc$/,/^mno$/{ /^abc$/d; /^mno$/d; p; }'

-n选项表示默认情况下不打印。

该模式查找仅包含abc到just的行mno,然后执行中的动作{ ... }。第一个动作删除该abc行;第二mno行;然后p打印剩余的行。您可以根据需要放松正则表达式。abc.. 范围以外的任何行都mno不会被打印。


感谢您的答复和解释!:)
dvai

@JonathanLeffler我可以知道使用的目的是什么-e
Kasun Siyambalapitiya

1
@KasunSiyambalapitiya:通常,这意味着我喜欢使用它。形式上,它指定下一个参数是sed应执行的脚本(的一部分)。如果要或需要使用几个参数来包含整个脚本,则必须-e在每个这样的参数之前使用;否则,请转入第二个。否则,它是可选的(但显式)。
乔纳森·莱夫勒

@JonathanLeffler谢谢
Kasun Siyambalapitiya

真好!(与awk相比,我更喜欢使用sed。)当使用复杂的正则表达式时,最好不必重复它们。是否可以删除“选定”范围的第一行/最后一行?还是先将应用于d第一个匹配之前的d所有行,然后再将其应用于从第二个匹配开始的所有行?
hans_meine 2016年

18

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

sed '/^abc$/,/^mno$/{//!b};d' file

删除除以abc和开头的行之间的行以外的所有行mno



这太棒了。在{//!b}防止abcmno被包含在输出,但我无法弄清楚如何。你能解释一下吗?
布伦丹

1
@Brendan,//!b如果当前行不是与范围匹配的行之一,则指令将读取并中断并打印这些行,否则将删除所有其他行。
potong '17

13
sed '/^abc$/,/^mno$/!d;//d' file

打高尔夫球比木棒好两个字符 {//!b};d

空的正斜杠//表示:“重用最后使用的正则表达式”。该命令与更易于理解的命令相同:

sed '/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d' file

似乎是POSIX

如果RE为空(即未指定任何模式),则sed的行为就像指定了所应用的最后一条命令(作为地址或作为替代命令的一部分)中使用的最后一个RE一样。


1
我认为第二个解决方案将一无所获,因为第二个命令也是一个范围。但是首先赞扬。
potong

@potong真的!我必须研究更多第一个为什么工作的原因。谢谢!
Ciro Santilli郝海东冠状病六四事件法轮功2015年

7

从上一个响应的链接来看,ksh在Solaris上运行的为我执行此操作的链接是:

sed '1,/firstmatch/d;/secondmatch/,$d'
  • 1,/firstmatch/d:从第1行开始,直到您第一次找到firstmatch,将其删除。
  • /secondmatch/,$d:从第一次出现secondmatch到文件结尾,删除。
  • 分号将两个命令分开,这两个命令按顺序执行。

很好奇,为什么范围限制器(1,)排在前面/firstmatch/?我猜这也可以表达'/firstmatch/1,d;/secondmatch,$d'吗?
路加·戴维斯

2
用“ 1,/ firstmatch / d”表示“从第1行开始,直到第一次找到'firstmatch',然后删除”。而使用“ / secondmatch /,$ d”则表示“从“ secondmatch”的第一次出现到文件末尾,删除”。以分号分隔的两个命令是按顺序执行的。
FanDeLaU

2
perl -lne 'print if((/abc/../mno/) && !(/abc/||/mno/))' your_file

很高兴知道perl等效项,因为它可以很好地替代awk和sed。
han

2

这样的事情对我有用:

file.awk:

BEGIN {
    record=0
}

/^abc$/ {
    record=1
}

/^mno$/ {
    record=0;
    print "s="s;
    s=""
}

!/^abc|mno$/ {
    if (record==1) {
        s = s"\n"$0
    }   
}

使用:awk -f file.awk data...

编辑:O_o fedorqui解决方案比我的更好/更漂亮。


3
在GNU中,awk if (record=1)应该是if (record==1),即重复= 查看gawk比较运算符
George Hawkins

2

Don_crissti的回答仅显示2个匹配模式之间的文本

firstmatch="abc"
secondmatch="cdf"
sed "/$firstmatch/,/$secondmatch/!d;//d" infile

比AWK的应用程序效率更高,请参阅此处


我认为链接时间比较在这里没有多大意义,因为问题的要求完全不同,因此也需要解决方案。
fedorqui'停止伤害'

2
我不同意,因为我们应该有一些比较答案的标准。只有少数具有SED应用程序。
莱奥列奥波尔德·赫兹준 영

0

我试图用来awk在两个模式之间打印行,而pattern2也匹配pattern1。并且pattern1线也应该被打印。

例如来源

package AAA
aaa
bbb
ccc
package BBB
ddd
eee
package CCC
fff
ggg
hhh
iii
package DDD
jjj

应该有一个输出

package BBB
ddd
eee

模式1在哪里 package BBB,pattern2是package \w*。请注意,这CCC不是一个已知值,因此无法进行字面匹配。

在这种情况下,@ scai awk '/abc/{a=1}/mno/{print;a=0}a' file或@fedorqui 都不awk '/abc/{a=1} a; /mno/{a=0}' file适合我。

最后,我设法解决这个问题awk '/package BBB/{flag=1;print;next}/package \w*/{flag=0}flag' file,哈哈

稍稍花点功夫awk '/package BBB/{flag=1;print;next}flag;/package \w*/{flag=0}' file,也就打印出pattern2行,即

package BBB
ddd
eee
package CCC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.