2010-12-20 150 views
143

我試圖使用grep來匹配包含兩個不同字符串的行。我已經嘗試了以下,但這匹配線包含string1string2這不是我想要的。如何使用grep匹配同一行中的多個字符串?

grep 'string1\|string2' filename 

那麼,如何配合grep僅包含兩個字符串行?

+1

相關:https://unix.stackexchange.com/questions/37313/how-do-i- grep-for-patterns- – 2018-01-03 09:06:37

回答

118

您可以使用grep 'string1' filename | grep 'string2'

或者,grep 'string1.*string2\|string2.*string1' filename

+2

嘗試多行 – 2013-03-15 20:47:11

+3

@AlexanderN的確我不能讓它與多行工作,這是如此奇怪,它被接受.. – 2013-10-24 03:23:49

+1

這不是一個多行問題。如果它是多行的,grep -P支持Perl風格的正則表達式... – 2014-11-28 15:02:07

3

|運算符在正則表達式中意味着或。也就是說,string1或string2將匹配。你可以這樣做:

grep 'string1' filename | grep 'string2' 

這將管道結果從第一個命令到第二個grep。這應該只給你兩條線匹配。

+0

你的陳述是真實的,但不回答OP問題 – 2017-07-24 19:03:30

7

你可以嘗試這樣的事:

(pattern1.*pattern2|pattern2.*pattern1) 
0

你應該有grep這樣的:

$ grep 'string1' file | grep 'string2' 
+0

這執行邏輯AND。 OP想要一個邏輯OR。 – 2017-07-24 19:02:55

12

如果你有一個grep-P選項有限perl正則表達式,你可以使用

grep -P '(?=.*string1)(?=.*string2)' 

其中有重疊的字符串工作的優勢。這有點更直接使用perlgrep,因爲你可以指定和更直接的邏輯:

perl -ne 'print if /string1/ && /string2/' 
+1

最佳答案。 Shell非常簡單快捷,但一旦模式變得複雜,您應該使用Python或Perl(或Awk)。不要打擊你的頭靠在牆上試圖證明它可以在純貝殼中完成(無論這些日子是什麼意思)。提醒人們,這些工具可以用於嵌入到現有shell腳本中的「單行」語法。 – 2014-11-28 15:06:45

159

我想這就是你要找的人:

grep -E "string1|string2" filename 

我認爲,答案是這樣的:

grep 'string1.*string2\|string2.*string1' filename 

只有匹配的情況下,兩者都存在,而不是一個或另一個或兩個。

+11

不會'grep -e「string1」-e「string2」文件名「做同樣的事情嗎? – janosdivenyi 2015-02-24 16:07:31

+1

另外egrep'string1 | string2 | string3'文件名可以工作。 – 2015-04-20 08:50:50

+12

這是如何grep爲string1或string2。問題清楚地表明他們正在尋找string1和string2。 – 2015-10-08 19:06:23

0

多行匹配:

echo -e "test1\ntest2\ntest3" |tr -d '\n' |grep "test1.*test3" 

echo -e "test1\ntest5\ntest3" >tst.txt 
cat tst.txt |tr -d '\n' |grep "test1.*test3\|test3.*test1" 

我們只需要刪除換行符和它的作品!

23

搜索包含在任何地方任何順序的所有單詞的文件:

grep -ril \'action\' | xargs grep -il \'model\' | xargs grep -il \'view_type\' 

第一grep的序幕遞歸搜索(r),忽略大小寫(i)和上市(打印出)的名稱(l)與文件中任何位置發生的一個詞('action'與單引號)匹配的文件。

隨後的greps搜索其他條款,保持大小寫不敏感並列出匹配的文件。

您將獲得的文件的最終列表將包含這些條款的文件,文件中任意位置的任何順序。

+0

同意!我只會注意到,我必須給xargs一個「-d'\ n'」來處理帶有空格的文件名。這在Linux上適用於我:'grep -ril'foo'| xargs -d'\ n'grep -il'bar'' – 2017-05-11 21:28:12

10

你的方法是差不多好了,只是缺少-w

grep -w 'string1\|string2' filename 
+0

這不行! – Ariel 2015-07-22 03:50:49

+1

至少在OS-X和FreeBSD上它確實有效!我的猜測是你還在別的東西上(OP沒有定義 - 希望你除了你以外對很多用戶都沒有正確的回答)。 – Leo 2015-07-23 07:27:13

+0

我在OS-X上。也許我沒有正確地做到這一點?看看我做了什麼:http://i.imgur.com/PFVlVAG.png – Ariel 2015-07-27 18:13:32

40

只要給它多-e選項。

-e pattern, --regexp=pattern 
     Specify a pattern used during the search of the input: an input 
     line is selected if it matches any of the specified patterns. 
     This option is most useful when multiple -e options are used to 
     specify multiple patterns, or when a pattern begins with a dash 
     (`-'). 

這樣的命令變爲:

grep -e "string1" -e "string2" filename 

注:以上我引用了BSD版本的手冊,但看起來像它the same on Linux

+11

注意:這匹配任何OP所要求的字符串中的任何一個,而不是兩個字符串。 – gustafbstrom 2016-10-05 09:52:14

0

把要grep命令查找到一個文件中的字符串

echo who > find.txt 
echo Roger >> find.txt 
echo [44][0-9]{9,} >> find.txt 

然後搜索使用-f

grep -f find.txt BIG_FILE_TO_SEARCH.txt 
1

發現線,只有6位開始,以完成:

cat my_file.txt | grep 
-e '^  .*(\.c$|\.cpp$|\.h$|\.log$|\.out$)' # .c or .cpp or .h or .log or .out 
-e '^  .*[0-9]\{5,9\}$' # numers between 5 and 9 digist 
> nolog.txt 
0
grep '(string1.*string2 | string2.*string1)' filename 

將獲得與字符串1和字符串行以任意順序

+0

與至少前兩個答案有什麼不同? – luk2302 2017-05-04 15:48:58

0

我經常遇到同樣的問題,因爲你,我只是寫了一段腳本:

function m() { # m means 'multi pattern grep' 

    function _usage() { 
    echo "usage: COMMAND [-inH] -p<pattern1> -p<pattern2> <filename>" 
    echo "-i : ignore case" 
    echo "-n : show line number" 
    echo "-H : show filename" 
    echo "-h : show header" 
    echo "-p : specify pattern" 
    } 

    declare -a patterns 
    # it is important to declare OPTIND as local 
    local ignorecase_flag filename linum header_flag colon result OPTIND 

    while getopts "iHhnp:" opt; do 
    case $opt in 
     i) 
     ignorecase_flag=true ;; 
     H) 
     filename="FILENAME," ;; 
     n) 
     linum="NR," ;; 
     p) 
     patterns+=("$OPTARG") ;; 
     h) 
     header_flag=true ;; 
     \?) 
     _usage 
     return ;; 
    esac 
    done 

    if [[ -n $filename || -n $linum ]]; then 
    colon="\":\"," 
    fi 

    shift $(($OPTIND - 1)) 

    if [[ $ignorecase_flag == true ]]; then 
    for s in "${patterns[@]}"; do 
      result+=" && s~/${s,,}/" 
    done 
    result=${result# && } 
    result="{s=tolower(\$0)} $result" 
    else 
    for s in "${patterns[@]}"; do 
      result="$result && /$s/" 
    done 
    result=${result# && } 
    fi 

    result+=" { print "$filename$linum$colon"\$0 }" 

    if [[ ! -t 0 ]]; then  # pipe case 
    cat - | awk "${result}" 
    else 
    for f in "[email protected]"; do 
     [[ $header_flag == true ]] && echo "########## $f ##########" 
     awk "${result}" $f 
    done 
    fi 
} 

用法:

echo "a b c" | m -p A 
echo "a b c" | m -i -p A # a b c 

如果你喜歡,你可以把它放在.bashrc中。

0

假設我們需要查找文件測試文件中多個單詞的計數。 有兩種方式去了解它

1)使用與正則表達式匹配模式

grep -c '\<\(DOG\|CAT\)\>' testfile 

2)使用egrep的命令

egrep -c 'DOG|CAT' testfile 

隨着你不必egrep的擔心表達grep命令並用管道分隔符分隔單詞。

0

而作爲人建議Perl和Python,和令人費解的shell腳本,在這裏簡單awk的方法:

awk '/string1/ && /string2/' filename 

說完看了看評論公認的答案:不,這並不做多-線;但那也不是這個問題的作者所要求的。

0
grep -i -w 'string1\|string2' filename 

這適用於完全相符的文字和匹配不區分大小寫的話,對於正在使用的-i

相關問題