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



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

必要时使用

带有标志的awk来触发打印:

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

这是如何工作的?

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

有关更详细的说明和示例,以及显示或不显示模式的情况,请参阅如何在两个模式之间选择线条?。

使用 sed

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

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

该模式查找仅包含 abc 到仅包含 mno 的行,然后执行{ ... }中的操作。 第一个操作删除abc行;第二条mno线;p打印剩余的行。 您可以根据需要放宽正则表达式。 超出abc范围的任何行..mno根本没有打印。

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

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

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

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

比普波东的{//!b};d好两个角色

空的正斜杠//表示:"重用最后一个使用的正则表达式"。 并且该命令的作用与更容易理解的相同:

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

这似乎是POSIX:

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

从上一个响应的链接来看,在 Solaris 上运行ksh为我做的是这样的:

sed '1,/firstmatch/d;/secondmatch/,$d'
  • 1,/firstmatch/d:从第 1 行到第一次找到 firstmatch 时,删除。
  • /secondmatch/,$d :从secondmatch第一次出现到文件结束,删除。
  • 分号分隔两个命令,这两个命令按顺序执行。

这样的东西对我有用:

文件.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解决方案比我的更好/更漂亮。

Don_crissti 的

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

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

这比AWK的应用程序效率高得多,请参阅此处。

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

我尝试使用awk来打印两个图案之间的线条,而模式2也匹配模式1。并且还应打印图案1行。

例如源

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,模式 2 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,也要打印图案2行,即

package BBB
ddd
eee
package CCC

这也可以通过对标志的逻辑运算和递增/递减运算来完成:

awk '/mno/&&--f||f||/abc/&&f++' file

最新更新