如何使用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中有什么方法可以重复执行直到文件结束?

#1 楼

必要时使用带有标志的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 flag:如果q4312079q等于1,则打印行。 br />
有关更详细的描述和示例,以及显示或不显示图案的情况,请参阅如何在两个图案之间选择线?。

评论


如果要打印包括图案在内的所有内容,则可以使用awk'/ abc / {a = 1} / mno / {print; a = 0} a'文件。

–scai
13年7月7日在8:08



是的,@ scai!甚至awk'/ abc / {a = 1} a; / mno / {a = 0}'文件-为此,在/ mno /之前放置一个条件,使它在设置a = 0之前将行评估为true(并打印)。这样我们可以避免写印刷品。

– fedorqui'停止伤害'
13年7月7日在9:43

@scai @fedorqui对于包括模式输出,您可以执行awk'/ abc /,/ mno /'文件

–乔特尼
2013年12月4日6:44



@hkasera awk'/ abc / {flag = 1} / mno / {flag = 0} flag'文件应为。

– fedorqui'停止伤害'
2014年12月11日在8:54

@EirNym是一个很奇怪的场景,可以用非常不同的方式处理:您要打印哪些行?可能是awk'标志; / PAT1 / {flag = 1; next} / PAT1 / {flag = 0}”文件生成。

– fedorqui'停止伤害'
17年4月24日在8:28

#2 楼

使用sed

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


-n选项意味着默认情况下不打印。然后执行abc中的动作。第一个动作删除mno行;第二条{ ... }线;然后abc打印剩余的行。您可以根据需要放松正则表达式。 mno .. p范围以外的任何行都不会被打印。

评论


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

– Kasun Siyambalapitiya
16 Dec 6'在4:33

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

–乔纳森·莱弗勒(Jonathan Leffler)
16 Dec 6'在4:41

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

–hans_meine
16 Dec 8'在10:12

(回复我自己的评论。)如果仅要剪切一个部分,我可以尝试解决此问题,例如对于LaTeX,请使用sed -n'1,/ \\\ begin {document} / d; / \\ end {document} / d; p'。 (这有点作弊,因为第二部分并没有删除到文档末尾,而且我不知道如何按照OP的要求剪切多个部分。)

–hans_meine
16 Dec 8'在10:50

@JonathanLeffler插入$标记的原因是什么,如/ ^ abc $等

– Kasun Siyambalapitiya
17年1月25日在4:58

#3 楼

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

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


删除除以abcmno开头的行之间的行以外的所有行

评论


!d; // d高尔夫2个字符更好:-) stackoverflow.com/a/31380266/895245

– Ciro Santilli郝海东冠状病六四事件法轮功
15年7月13日在9:54

这太棒了。 {//!b}可以防止abc和mno包含在输出中,但是我不知道如何。你能解释一下吗?

–布伦丹
17年2月16日在17:44

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

–potong
17年2月17日在1:14

#4 楼

sed '/^abc$/,/^mno$/!d;//d' file
比potpotong的{//!b};d高两个字符,而空的正斜杠//的意思是:“重用最后使用的正则表达式”。并且该命令与更易于理解的命令相同:

sed的行为就像指定了所应用的最后一个命令中使用的最后一个RE(作为地址或作为替代命令的一部分)。

评论


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

–potong
15年7月13日在14:20



@potong真的!我必须研究更多第一个为什么工作的原因。谢谢!

– Ciro Santilli郝海东冠状病六四事件法轮功
15年7月13日在14:22



#5 楼

从上一个响应的链接来看,为我做的一个在Solaris上运行ksh的操作是:第1行,直到第一次找到1,/firstmatch/d,删除。

firstmatch:从/secondmatch/,$d的第一次出现到文件末尾,删除。
分号分隔两个命令,它们在顺序。


评论


很好奇,为什么范围限制器(1,)在/ firstmatch /之前?我猜这也可以写成'/ firstmatch / 1,d; / secondmatch,$ d'吗?

–卢克·戴维斯(Luke Davis)
18 Jun 25'在0:40



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

– FanDeLaU
18/12/20在17:18

#6 楼

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


评论


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

– akhan
17 Mar 8 '17 at 23:46

#7 楼

这样的东西对我有用:

file.awk:

BEGIN {
    record=0
}

/^abc$/ {
    record=1
}

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

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


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

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

评论


在GNU awk中,if(record = 1)应该是if(record == 1),即double =-请参见gawk比较运算符

–乔治·霍金斯(George Hawkins)
2014年5月26日晚上8:53

#8 楼

Don_crissti的答案来自仅显示2个匹配模式之间的文本?

评论


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

– fedorqui'停止伤害'
2015年9月11日15:11

我不同意,因为我们应该有一些比较答案的标准。只有少数具有SED应用程序。

–LéoLéopoldHertz준영
2015年9月11日在16:10

#9 楼

我尝试使用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


pattern1是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都不适合我。 br />最后,我设法通过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
< />