我有一个很长的日志文件,其中每个条目都以仅包含连字符的行开头。
答案1
你可以使用 shell 脚本来做这件事:
#!/bin/bash
if [[ -z "$1" ]] ; then
echo Usage: $0 '<inputFile>'
exit 1
fi
line=$(grep -n '^--*$' "$1" | tail -1 | sed 's/:.*//')
if [[ -z "${line}" ]] ; then
cat "$1"
else
sed "1,${line}d" "$1"
fi
给定输入文件:
this is line 1
-------
this is line 3
-------
this is line 5
this is line 6
它产生:
this is line 5
this is line 6
为了解释,grep -n
产生了一系列类似这样的行:
2:-------
4:-------
其中2
和4
是行号。thentail -1
会过滤掉除最后一个之外的所有内容,而sed
会删除从冒号到行尾的所有内容,只留下行号
然后,如果没有符合所需模式的行,它只会输出整个文件。否则它会删除 1 和最后一个连字符行之间的所有行。
顺便说一句,我最初的答案包括这个awk
代码片段,它只会处理该文件一次:
awk '/^--*$/{s=""}{s=s$0"\n";}END{print s}'
但是,请记住,它的工作原理是将行累积成一个字符串,并在找到连字符时清除该字符串。然后,最后,它只是输出字符串(最后一个连字符行之后的所有行)。
虽然乍一看,这似乎更有效率,但实际上并非如此。在我的系统上进行的(诚然不是详尽的)测试中,它实际上运行得相当慢,我认为这与正在进行的许多字符串附加有关。事实上,尽管脚本解决方案对数据进行了多次传递(可能是因为每次传递的功能非常有限),但它似乎更快。
答案2
awk -vRS="-+" 'END{print}' ORS="" file
答案3
你也可以用 sed 来做:
% cat t.txt
this is line 1
this is line 2
-------
this is line 3
----
this is line 4
-------
this is line 5
this is line 6
% sed -n -e '/^---*/{h;d;}' -e H -e '${g;p;}' t.txt
-------
this is line 5
this is line 6
%
(对于某些 sed,这些分号必须是换行符)。
答案4
tac file | grep -B 10000 -m 1 -- '------' | tac