如何显示从头到某些多行模式的文件内容不包括模式本身?
例如,如果我有一个像这样的文本文件:
cat
dog
fox
cow
dove
bird
bunny
gnu
hen
dove
bird
buffalo
如果我的模式是这样的:
dove
bird
bunny
我想要得到的是:
cat
dog
fox
cow
我的真实文件很大,因此如果有多种方法可以实现此目的,我更喜欢更快的方法。
另外,我刚才问了一个与此相关的类似问题,但它是不同的,所以请不要仅仅因为这个就将其标记为重复!
答案1
您可以使用逐行处理输入sed
并链接多行模式匹配:
/pat1/ { N; N; ...; /pat2\npat3\n.../q }
所以在你的例子中,那就是:
sed -n '/^dove$/ { N; N; /\nbird\nbunny$/q; }; p' infile
输出:
cat
dog
fox
cow
答案2
这是另一种sed
方法,它使用分支在模式空间中维护一个 3 行缓冲区,并根据多行模式对其进行测试,找到时退出:
sed -n '
:a
$q
N
/dove\nbird\nbunny/q
3,$ {
P
D
}
ba
' file
使用 GNU sed,您可以使用Q
命令退出而不打印当前模式空间,而且它允许更自由格式的语法,例如
sed -e :a -e '$Q' -e 'N;/dove\nbird\nbunny/Q' -e '3,${P;D}' -e 'ba' file
或者
sed ':a; $Q; N; /dove\nbird\nbunny/Q; 3,${P;D}; ba' file
答案3
这里有一些 Python hack 可以做到这一点。
代码:
# !/usr/bin/python
import sys
with open(sys.argv[2], 'rU') as f:
patterns = f.readlines()
result = None
with open(sys.argv[3], 'rU') as f:
last_match = 0
for i, line in enumerate(f):
if line != patterns[last_match]:
last_match = 0
else:
last_match += 1
if last_match == len(patterns):
result = i + 1 - len(patterns)
break
if result != None:
if sys.argv[1] == 'tail':
print("tail -n+%d %s" % (result+1, sys.argv[3]))
else:
print("head -n%d %s" % (result, sys.argv[3]))
运行
要输出最多模式:
`python split_on_pattern.py head pattern_file data_file`
要从模式输出:
`python split_on_pattern.py tail pattern_file data_file`