How to find patterns across multiple lines using grep?

后端 未结 26 1525
你的背包
你的背包 2020-11-22 04:14

I want to find files that have \"abc\" AND \"efg\" in that order, and those two strings are on different lines in that file. Eg: a file with content:

blah bl         


        
相关标签:
26条回答
  • 2020-11-22 04:38

    sed should suffice as poster LJ stated above,

    instead of !d you can simply use p to print:

    sed -n '/abc/,/efg/p' file
    
    0 讨论(0)
  • 2020-11-22 04:38

    You can do that very easily if you can use Perl.

    perl -ne 'if (/abc/) { $abc = 1; next }; print "Found in $ARGV\n" if ($abc && /efg/); }' yourfilename.txt
    

    You can do that with a single regular expression too, but that involves taking the entire contents of the file into a single string, which might end up taking up too much memory with large files. For completeness, here is that method:

    perl -e '@lines = <>; $content = join("", @lines); print "Found in $ARGV\n" if ($content =~ /abc.*efg/s);' yourfilename.txt
    
    0 讨论(0)
  • 2020-11-22 04:39

    If you need both words are close each other, for example no more than 3 lines, you can do this:

    find . -exec grep -Hn -C 3 "abc" {} \; | grep -C 3 "efg"
    

    Same example but filtering only *.txt files:

    find . -name *.txt -exec grep -Hn -C 3 "abc" {} \; | grep -C 3 "efg"
    

    And also you can replace grep command with egrep command if you want also find with regular expressions.

    0 讨论(0)
  • 2020-11-22 04:39

    you can use grep incase you are not keen in the sequence of the pattern.

    grep -l "pattern1" filepattern*.* | xargs grep "pattern2"
    

    example

    grep -l "vector" *.cpp | xargs grep "map"
    

    grep -l will find all the files which matches the first pattern, and xargs will grep for the second pattern. Hope this helps.

    0 讨论(0)
  • 2020-11-22 04:39

    If you have some estimation about the distance between the 2 strings 'abc' and 'efg' you are looking for, you might use:

    grep -r . -e 'abc' -A num1 -B num2 | grep 'efg'
    

    That way, the first grep will return the line with the 'abc' plus #num1 lines after it, and #num2 lines after it, and the second grep will sift through all of those to get the 'efg'. Then you'll know at which files they appear together.

    0 讨论(0)
  • 2020-11-22 04:40

    I don't know how I would do that with grep, but I would do something like this with awk:

    awk '/abc/{ln1=NR} /efg/{ln2=NR} END{if(ln1 && ln2 && ln1 < ln2){print "found"}else{print "not found"}}' foo
    

    You need to be careful how you do this, though. Do you want the regex to match the substring or the entire word? add \w tags as appropriate. Also, while this strictly conforms to how you stated the example, it doesn't quite work when abc appears a second time after efg. If you want to handle that, add an if as appropriate in the /abc/ case etc.

    0 讨论(0)
提交回复
热议问题