如何根据连续两行的内容对目录进行grep?


11

如何为包含“ Foo”但在下一行也包含“ Bar”的行中获得匹配项的目录 grep ?


现在的问题与原始问题完全不同:/也许最好还原旧版本并发布另一个版本?此外,新问题对我来说还不清楚。
吉尔斯·奎诺

@sputnick-怎么回事?我第一次发布问题时指定了一个目录;我只是加粗了它,因为人们没有注意到。
内森·朗

没关系,这将起作用,我将相应地编辑我的POST。
吉尔斯·奎诺

Answers:


7

@ warl0ck使用指向我正确的方向pcregrep,但是我说“包含”,而不是“是”,然后我询问目录,而不是文件。

这似乎为我工作。

pcregrep -rMi 'Foo(.*)\n(.*)Bar' .

6

Grep本身似乎不支持它,请改用pcregrep:

Foo
Bar
Foo
abc

pcregrep -M "Foo\nBar" file

得到了:

Foo
Bar

3
该OP没有说FooBar将包括整条生产线。
tojrobinson 2012年

6

使用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 spacehold space 这里的信息

grymoire.com的shell编程知识真的很棒。


什么h, n, H, x, p, q意思 很有意思。
Yamaneko

查看我的评论。有关pattern space&的更多信息hold spacegrymoire.com/Unix/Sed.html#uh-56或法文注释camarche.net/faq/9536-sed-introduction-a-sed-part-i
Gilles Quenot 2012年

POST适应工作的一个目录
吉尔斯Quenot

4

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 Long

这还将在同一行上列出同时出现“ Foo”和“ Bar”的事件。
manatwork,2012年

@manatwork:包含“ Foo”和“ Bar”的行就是“包含'Foo'的行”,这就是要问的。
tojrobinson 2012年

1
@tojrobinson,“但在下一行还包含“ Bar”的部分时才获得匹配”怎么办?pastebin.com/Yj8aeCEA
manatwork

3

虽然我更喜欢使用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

1
酷把戏什么-z。整个表达式前后的一些“(。*)”将使其输出整个匹配的行。目前,不显示“ Foo”之前和“ Bar”之后的子字符串。
manatwork,2012年

1

使用awk:

awk '/bar/ && prev != "" {print FILENAME ": " prev "\n" FILENAME ": " $0}
     /foo/ {prev=$0; next}
     {prev=""}' file1...

(有关awk限制的一般说明:请注意,如果某些文件名可能包含“ =”字符,则需要将其作为./filename而不是传递filename给awk)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.