Awk 如何获取包含某个字符串的行与另一个包含另一个字符串的行加上前面的行之间的所有行

Awk 如何获取包含某个字符串的行与另一个包含另一个字符串的行加上前面的行之间的所有行,awk,Awk,我花了一些时间在网上搜索,但没有找到答案。 假设我有一个包含以下行的文件: aaaaaaa vvvvv ggggg yyyyyyyyy ffffff rrrrrrrr uuuuu ssssssssssss zzzzz hhhhhhhh 我知道如何使用awk查找从包含“ffffff”到包含“UUU”的所有行: awk '/ffffff/,/uuuuu/' file 但是,我怎样才能同时得到我找到的第一行之前的那一行(即“yyyyyyyyy”)?有没有像grep-b1这样的东西可以做到这一点?

我花了一些时间在网上搜索,但没有找到答案。 假设我有一个包含以下行的文件:

aaaaaaa
vvvvv
ggggg
yyyyyyyyy
ffffff
rrrrrrrr
uuuuu
ssssssssssss
zzzzz
hhhhhhhh
我知道如何使用awk查找从包含“ffffff”到包含“UUU”的所有行:

awk '/ffffff/,/uuuuu/' file
但是,我怎样才能同时得到我找到的第一行之前的那一行(即“yyyyyyyyy”)?有没有像grep-b1这样的东西可以做到这一点? 我想得到的是:

yyyyyyyyy
ffffff
rrrrrrrr
uuuuu

提前感谢。

您可以使用此
awk

awk'/ffffff/{flag=1;prev=p}flag{if(prev!=“”)print prev;prev=“”;print}/uuuuuu/{flag=0}{p=$0}文件
YYYYYYYY
ffffff
rrrrrrrr
乌乌
轻微的变化

$ awk '/fffff/{print p; f=1} f; /uuuuu/{f=0} {p=$0}' file

yyyyyyyyy
ffffff
rrrrrrrr
uuuuu
假设开始/结束标记不重叠,但可以存在多次

说明:首先开始
fffff
它将打印前一行(在p中捕获)并设置一个标志<代码>f表示如果设置了标志,则打印当前行,缩写为
f==1{print$0}
。Next语句在看到
uuu
时重置标志,最后我们捕获要在第一个语句中使用的行;这似乎是不必要的,除了一种情况,它的使用,但最有可能比每次比较便宜


请注意,这可能是使用有限的功能处理边缘情况(多个开始/结束标记、无结束标记等)所能获得的最简单脚本。

另一个
awk
使用循环
for

awk -v OFS='\n'  '{for (i=1; i<=NF; i++) if ($i == "ffffff"|| $i == "uuuuu") print p,$0} {p=$0}' file
yyyyyyyyy
ffffff
rrrrrrrr
uuuuu

如果输入中同时存在ffffff和UUUU,则仅打印,如果ffffff是输入中的第一行,则不打印空行:

$ cat tst.awk
/ffffff/ { f = 1 }
f {
    rec = rec $0 ORS
    if ( /uuuuu/ ) {
        printf "%s", rec
        f = 0
    }
    next
}
{ rec = $0 ORS }

$ awk -f tst.awk file
yyyyyyyyy
ffffff
rrrrrrrr
uuuuu

!f&&/ffffff/
修复了不匹配的情况,我认为这在我的情况下效果非常好,但是…所以我需要阅读手册才能理解…谢谢你的帮助。@Stantheman如果
uuuuu
不存在,这是从第一个
fffff
到文件结尾的答案之一-这是期望的行为吗?@Ed Morton不是真的。但我不确定在这种情况下什么是最好的行为。复制所有行直到文件结束不是我想要的,因为我的目标是将500米日志中的有用数据保存到一个~250k的文件中。但另一方面,它将生成原始日志文件的部分备份(将被擦除)…您始终可以根据数据是否采用您希望决定是否应复制原始文件的格式来设置/使用awk脚本的退出状态。如果输入中不存在UUU,您得到的一些答案将从fffff打印文本,直到文件结束-这是正确的行为吗?如果UUU存在且没有前面的ffffff,则有些会打印-正确吗?另外,应该如何处理嵌套和/或重叠分隔符?这些都是很好的问题。我没有想到这一点,假设我的文件是正确的,也就是说,总是有第一个字符串和第二个字符串……但是你是对的,假设它总是正确的,这可能不是一个好主意……在非晴天的情况下,打印你想要的文本总是很琐碎,而不打印你不想要的文本要困难得多。一些答案的另一个问题是,如果
ffffffff
显示为输入的第一行,他们将在ffffff->uuuuu文本前打印一个空行-这是所需的行为吗?我很确定ffffff永远不会出现在第一行。在我的情况下,它也会起作用,谢谢!在我的例子中,这没有得到任何结果,但可能是因为我正在Cygwin中测试它……我将在Linux中尝试。不管怎样,谢谢你的帮助。不,这与cygwin无关。事实上,当我编写和测试cygwin时,我自己也在使用它。如果它不适用于您,则可能是您复制/粘贴不正确,或者您正在运行它的数据看起来与问题中的数据不一样(例如,可能您没有
uuuu
存在)。如果你运行我在你发布的示例输入上发布的脚本,它将生成你发布的预期输出。哎呀,你说得对,我打错了。你的答案很正确。
$ cat tst.awk
/ffffff/ { f = 1 }
f {
    rec = rec $0 ORS
    if ( /uuuuu/ ) {
        printf "%s", rec
        f = 0
    }
    next
}
{ rec = $0 ORS }

$ awk -f tst.awk file
yyyyyyyyy
ffffff
rrrrrrrr
uuuuu