Answers:
Grep本身似乎不支持它,请改用pcregrep:
Foo
Bar
Foo
abc
pcregrep -M "Foo\nBar" file
得到了:
Foo
Bar
Foo
和Bar
将包括整条生产线。
使用sed
脚本:
#!/bin/sed -nf
/^Foo/{
h # put the matching line in the hold buffer
n # going to nextline
/^Bar/{ # matching pattern in newline
H # add the line to the hold buffer
x # return the entire paragraph into the pattern space
p # print the pattern space
q # quit the script now
}
}
要使用它:
chmod +x script.sed
printf '%s\n' * | ./script.sed
在printf
这里展示的每一条线在当前目录下的所有文件,并将它传递给sed
。
注意:这是按字母顺序排序的。
更多有用pattern space
和hold space
这里的信息。
grymoire.com的shell
编程知识真的很棒。
h, n, H, x, p, q
意思 很有意思。
pattern space
&的更多信息hold space
:grymoire.com/Unix/Sed.html#uh-56或法文注释camarche.net/faq/9536-sed-introduction-a-sed-part-i
grep
仅使用,就可以构造以下管道:
grep -A1 'Foo' input_file | grep -B1 'Bar' | grep 'Foo'
第一个grep
将获取包含的所有行Foo
以及比赛后的行。然后我们得到包含Bar
以及匹配之前的行的行,最后从此输出中提取包含的行Foo
。
编辑:正如manatwork指出,有一些问题的情况需要观察。尽管由于grep
面向行的功能,这是一个有趣的挑战,但采用它的任何解决方案都可能是“黑客”,您最好使用pcregrep
更适合手头任务的工具。
find . -name '*.txt' | xargs grep -A1 'Foo' | grep -B1 'Bar'
虽然我更喜欢使用Nathan的解决方案pcregrep
,但这是仅使用grep的解决方案
grep -o -z -P 'Foo(.*)\n(.*)Bar' file
选项说明:
-o
只打印匹配的部分。由于包含必需,-z
将打印出整个文件(除非某处有\ 0)-z
将输入视为一组行,每行以零字节(ASCII NUL字符)而不是换行符结尾。-P
perl regex语法 编辑:此版本打印出整个匹配的行
grep -o -P -z '(.*)Foo(.*)\n(.*)Bar(.*)' file
-z
。整个表达式前后的一些“(。*)”将使其输出整个匹配的行。目前,不显示“ Foo”之前和“ Bar”之后的子字符串。
使用awk:
awk '/bar/ && prev != "" {print FILENAME ": " prev "\n" FILENAME ": " $0}
/foo/ {prev=$0; next}
{prev=""}' file1...
(有关awk限制的一般说明:请注意,如果某些文件名可能包含“ =”字符,则需要将其作为./filename
而不是传递filename
给awk)