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

时间:2017-07-03 00:37:36

标签: 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
Checking log log2.txt
34
56
78
Checking log log5.txt
90

模式是“正在检查”

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

7 个答案:

答案 0 :(得分:3)

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

$ 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次迭代是我的限制: - )。

答案 1 :(得分:3)

使用像awk或perl这样的语言要容易得多,但这就是魔术:

sed -e '/[^0-9]/{ h; d; }; H; x; 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

答案 2 :(得分:2)

使用void *

的另一个简单解决方案
pcregrep

答案 3 :(得分:1)

如果您更喜欢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

答案 4 :(得分:1)

您可以使用sed中的保留空间以及交换(或x [check here] 选项以及一些分支(或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方法提及[here]是最简单的方法。

答案 5 :(得分:1)

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

答案 6 :(得分:1)

sed 'N;/^[^0-9].*\n[^0-9]/!P;D'