如何在包括它们的两个模式之间选择首次出现


27

如何在包括它们的两个模式之间选择首次出现。最好使用sedawk

我有:

text
something P1 something
content1
content2
something P2 something
text
something P1 something
content3
content4
something P2 something
text

我想第一次出现P1和P2之间的线(包括P1线和P2线):

something P1 something
content1
content2
something P2 something

Answers:


22
sed '/P1/,/P2/!d;/P2/q'

...将d删除!不属于该范围的所有行,然后q第一次遇到范围的末尾,便可以轻而易举地完成这项工作。对于在P1之前的P2,它不会失败,并且不需要GNU特定语法即可简单地编写。


优秀!比我的好多了。
muru

1
@muru-如果尝试定位自动打印,通常更容易避免扭曲-让循环为您工作。无论如何,这就是我养成的习惯。我认为最好将其描述为修剪选择方法-我倾向于否定模式而不是寻找模式。
mikeserv

处理巨大的fileSize时,它将挂起。
Brain90 '17

@ Brain90-不应该。如果您可以可靠地重现您的投诉,则应向您的维护者sed寻求帮助……多数民众赞成在sed您运行中的一个错误,而不是上面的脚本中的错误。
mikeserv

1
@mikeserv如果不是我就不会说。您对我是否关心几个字符的担忧很奇怪:我观察到sed表达式/P2/q在我的系统中无论有无都可以工作;而已。我对某些事情感到好奇,并想分享我的发现。
Alexej Magura

8

awk

awk '/P1/{a=1};a;/P2/{exit}' file
something P1 something
content1
content2
something P2 something

8

sed

sed -n '/P1/,/P2/p; /P2/q'
  • -n取消默认打印,然后使用p命令在匹配的地址范围之间打印行。
  • 通常,这将匹配两个部分,因此q在第一个P2匹配时退出()。

如果a P2之前出现,则将失败P1。要处理这种情况,请尝试:

sed -n '/P1/,/P2/{p; /P2/q}'

1
我不同意; mikeserv的答案并没有比您的答案更好。
G-Man说“恢复莫妮卡”

@ g-man-pshaw。但是我只是在想同样的事情。
mikeserv

1
@gman-不 现在我懂了。我的方式更好。不{堆栈}!
mikeserv

1

如果您想自己跳过模式,请使用以下awk版本:

awk '/P2/ {exit} /P1/ {f=1; next} f' file

为我工作。您能否添加有关该命令如何工作的更多信息?
0xAffe

1

一个更简单的awk解决方案(介于 iruvar答案和  muru答案之间,但不使用变量):

awk '/P1/,/P2/ { print }  /P2/ { exit }'

并且,如专家指出,如果第一个P2出现在第一个P1之前,则不会打印任何内容。

当然,如果要打印所有P1-P2范围:

something P1 something
content1
content2
something P2 something
something P1 something
content3
content4
something P2 something

只需省略exit一部分:

awk '/P1/,/P2/ { print }'

1
awk '/P1/,/P2/{print;f=1} f&&/P2/{exit}' data

打印后立即退出,而不是之前退出。


0

要跳过模式本身,并在单个GNU sed中仅显示第一个匹配的块:

sed -nre '/STARTPATTERN/ {:a;n;/ENDPATTERN/{b;};p;ba}' file
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.