How to find patterns across multiple lines using grep?

后端 未结 26 1677
你的背包
你的背包 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:29

    With ugrep released a few months ago:

    ugrep 'abc(\n|.)+?efg'
    

    This tool is highly optimized for speed. It's also GNU/BSD/PCRE-grep compatible.

    Note that we should use a lazy repetition +?, unless you want to match all lines with efg together until the last efg in the file.

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

    If you are willing to use contexts, this could be achieved by typing

    grep -A 500 abc test.txt | grep -B 500 efg
    

    This will display everything between "abc" and "efg", as long as they are within 500 lines of each other.

    0 讨论(0)
  • 2020-11-22 04:34
    #!/bin/bash
    shopt -s nullglob
    for file in *
    do
     r=$(awk '/abc/{f=1}/efg/{g=1;exit}END{print g&&f ?1:0}' file)
     if [ "$r" -eq 1 ];then
       echo "Found pattern in $file"
     else
       echo "not found"
     fi
    done
    
    0 讨论(0)
  • 2020-11-22 04:34

    This should work:

    cat FILE | egrep 'abc|efg'
    

    If there is more than one match you can filter out using grep -v

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

    Why not something simple like:

    egrep -o 'abc|efg' $file | grep -A1 abc | grep efg | wc -l
    

    returns 0 or a positive integer.

    egrep -o (Only shows matches, trick: multiple matches on the same line produce multi-line output as if they are on different lines)

    • grep -A1 abc (print abc and the line after it)

    • grep efg | wc -l (0-n count of efg lines found after abc on the same or following lines, result can be used in an 'if")

    • grep can be changed to egrep etc. if pattern matching is needed

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

    Here is a solution inspired by this answer:

    • if 'abc' and 'efg' can be on the same line:

        grep -zl 'abc.*efg' <your list of files>
      
    • if 'abc' and 'efg' must be on different lines:

        grep -Pzl '(?s)abc.*\n.*efg' <your list of files>
      

    Params:

    • -P Use perl compatible regular expressions (PCRE).

    • -z Treat the input as a set of lines, each terminated by a zero byte instead of a newline. i.e. grep treats the input as a one big line.

    • -l list matching filenames only.

    • (?s) activate PCRE_DOTALL, which means that '.' finds any character or newline.

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