Bash UNIX sed:如果下一行不是数字(或与相同模式匹配),如何删除具有模式的行?

Bash UNIX sed:如果下一行不是数字(或与相同模式匹配),如何删除具有模式的行?,bash,unix,awk,sed,sh,Bash,Unix,Awk,Sed,Sh,以下是示例文本文件: $ cat text.txt Checking log log0.txt 12 Checking log log1.txt Checking log log2.txt 34 56 78 Checking log log3.txt Checking log log4.txt Checking log log5.txt 90 如何使用sed(或任何其他工具)处理它,因此它将如下所示: $ cat text.txt Checking log log0.txt 12 Checki

以下是示例文本文件:

$ cat text.txt
Checking log log0.txt
12
Checking log log1.txt
Checking log log2.txt
34
56
78
Checking log log3.txt
Checking log log4.txt
Checking log log5.txt
90
如何使用sed(或任何其他工具)处理它,因此它将如下所示:

$ cat text.txt
Checking log log0.txt
12
Checking log log2.txt
34
56
78
Checking log log5.txt
90
模式是“检查”

更新:
如果最后一行有“检查”模式,也应将其删除。

如果这不是您所需要的全部:

$ awk '/Checking/{p=$0 ORS; next} {printf "%s", p; p=""; print} END{printf "%s", p}' file
Checking log log0.txt
12
Checking log log2.txt
34
56
78
Checking log log5.txt
90
然后编辑你的问题,包括一个更具代表性的例子

在你的评论中写下下面的问题,这可能是你想要的:

$ awk '/Checking/{p=$0 ORS; next} {printf "%s", p; p=""; print} END{if (p !~ /Checking/) printf "%s", p}' file
通过在前一行而不是当前行上进行操作,可能有一种方法可以避免重复条件,但问题的2次迭代是我的限制:-)。

如果您喜欢sed:

$ cat test.sed
# If line starts with a number:
/^[0-9]/{
# Exchange hold space and patter space
x
# If line is not empty, print it
/^..*/p
# Exchange again
x
# Print the line
p
# Empty contents of pattern space
s/^.*$//
# Put empty line in hold space
h
}

# If line starts with 'Checking' put it in hold space
/^Checking/h

$ cat test.txt
Checking log log0.txt
12
Checking log log1.txt
Checking log log2.txt
34
56
78
Checking log log3.txt
Checking log log4.txt
Checking log log5.txt
90

$ sed -n -f test.sed test.txt
Checking log log0.txt
12
Checking log log2.txt
34
56
78
Checking log log5.txt
90

使用awk或perl这样的语言更容易做到这一点,但神奇之处在于:

sed-e'/[^0-9]/{h;d;};Hx;s/[0-9]\+\n//g;'text.txt

这里的神奇之处在于,它利用了sed有限的分支和保持空间功能以及一些更深奥的命令。将其分解为可解释的部分:

/^[0-9]/ {     # for any line with a non-numeric character...
    h          # replace hold space with the line
    d          # move onto next line of input without printing anything
}
H              # Append the current line (one that is necessarily entirely
               # numeric to the hold space
x              # swap the input & hold space
s/[0-9]\+\n//g # Delete an all numeric value + carriage return
               # from start of the input space
               #
               # Content of input space prints here

您可以利用sed中的保留空间以及exchange(或
x
)选项和一些分支(或
b
)来实现您的目标,如下所示

# cat 44876377
Checking log log0.txt
12
Checking log log1.txt
Checking log log2.txt
34
56
78
Checking log log3.txt
Checking log log4.txt
Checking log log5.txt
90
# sed -En '/^Checking/h;/^[0-9]+$/{x;G;:l;p;n;/^[0-9]+$/bl}' 44876377
Checking log log0.txt
12
Checking log log2.txt
34
56
78
Checking log log5.txt
90


注意:尽管我觉得上面提到的
awk
方法是最简单的方法。

另一个使用
pcregremp的简单解决方案

$ pcregrep -M "^.*$\n\d+" text.txt 
Checking log log0.txt
12
Checking log log2.txt
34
56
78
Checking log log5.txt
90
GNU
grep
,使用
-B
-before context
选项:

grep --no-group-separator -B 1 '^[0-9]\+$' text.txt
输出:

Checking log log0.txt
12
Checking log log2.txt
34
56
78
Checking log log5.txt
90

@达维姆:我没有否决这一点,但我很确定这是因为op没有以代码的形式努力解决他们的问题。这对于一个已经陷入如此境地一段时间的人来说是非常明显和不可接受的。@DavyM我同意你的观点,因为发表评论说明为什么有人否决了一个问题是合乎道德的,这就是为什么你和我:)。但最终还是要由用户来决定。@DavyM我同意你的看法。@sjsam实际上,在这里提问之前,我自己已经花了好几个小时了。由于缺乏sed/awk知识,我的代码很傻,我不想在这里分享。没有意义。@hellish不知道什么是可以的,但在将来发布问题时,尝试至少包含伪代码以显示您的努力。很高兴你得到了答案。如果其中任何一个帮助您解决了问题,您可以接受该问题,以便将此问题标记为已解决:)谢谢!!这是完美的,它甚至删除了最后一行,如果它只包含“检查”模式,这不是我的例子(我的坏)。谢谢Ed。它可以工作,但如果最后一行包含“检查”模式,它不会被删除。抱歉,示例不够好(我的不好)。请更新您的问题,以包含足够好的示例,这样我们就不会再犯错误。无论如何,我在答案的结尾添加了一个可能的解决方案。对于最后一个文件为空的情况,另一个可能的解决方案可能如下:
awk'/Checking/{p=$0 ORS;next}{printf“%s”,p;p=“”;print}end{if(getline==1){printf“%s”,p}}文件
只有一个输入文件。我不明白你认为问题是什么,但如果你在结束部分,那么你已经到达了输入的结尾,因此getline肯定会失败,所以无论你认为问题是什么,都无法解决它。
sed 'N;/^[^0-9].*\n[^0-9]/!P;D'