从头到多行模式显示文件内容

从头到多行模式显示文件内容

如何显示从头到某些多行模式的文件内容不包括模式本身?

例如,如果我有一个像这样的文本文件:

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`

相关内容