web-dev-qa-db-ja.com

異なる行にあるファイル内の複数の文字列のgrep(つまり、行ベースの検索ではなくファイル全体)

任意の行にDanskSvenska、またはNorskという単語を含むファイルを、使用可能なリターンコードでgrepしたい(文字列が含まれています、私のワンライナーはこれから少し先に進みます)。

次のような行が含まれる多くのファイルがあります。

Disc Title: unknown
Title: 01, Length: 01:33:37.000 Chapters: 33, Cells: 31, Audio streams: 04, Subpictures: 20
        Subtitle: 01, Language: ar - Arabic, Content: Undefined, Stream id: 0x20, 
        Subtitle: 02, Language: bg - Bulgarian, Content: Undefined, Stream id: 0x21, 
        Subtitle: 03, Language: cs - Czech, Content: Undefined, Stream id: 0x22, 
        Subtitle: 04, Language: da - Dansk, Content: Undefined, Stream id: 0x23, 
        Subtitle: 05, Language: de - Deutsch, Content: Undefined, Stream id: 0x24, 
(...)

ここに私が欲しいものの擬似コードがあります:

for all files in directory;
 if file contains "Dansk" AND "Norsk" AND "Svenska" then
 then echo the filename
end

これを行う最良の方法は何ですか? 1行で実行できますか?

78
Christian

次を使用できます。

grep -l Dansk * | xargs grep -l Norsk | xargs grep -l Svenska

隠しファイルも検索したい場合:

grep -l Dansk .* | xargs grep -l Norsk | xargs grep -l Svenska
84
vmpstr

Bashとgrepだけを使用する別の方法:

単一ファイル「test.txt」の場合:

 grep -q Dansk test.txt && grep -q Norsk test.txt && grep -l Svenska test.txt 

test.txtファイルに3つすべてが含まれている場合(任意の組み合わせ)。最初の2つのgrepsは何も出力しません(-q)最後のファイルは、他の2つが合格した場合にのみファイルを印刷します。

ディレクトリ内のすべてのファイルに対して実行する場合:

 for f in *; do grep -q Dansk $ f && grep -q Norsk $ f && grep -l Svenska $ f;完了
21
Edd Steel
grep –irl Word1 * | grep –il Word2 `cat -` | grep –il Word3 `cat -`
  • -iは大文字と小文字を区別せずに検索します
  • -rファイル検索をフォルダー全体に再帰的にします
  • -l見つかったWordでファイルのリストをパイプします
  • cat -は、次のgrepにリストに渡されたファイルを調べさせます。
15
Gerry

異なる行のファイル内の複数の文字列をgrepする方法(パイプ記号を使用):

for file in *;do 
   test $(grep -E 'Dansk|Norsk|Svenska' $file | wc -l) -ge 3 && echo $file
done

ノート:

  1. 二重引用符を使用する場合""をgrepで使用すると、次のようにパイプをエスケープする必要があります:\| Dansk、Norsk、Svenskaを検索します。

  2. 1行に言語が1つしかないと仮定します。

チュートリアル: http://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/

10
Damodharan R

これは、複数のファイルで複数の単語を検索します。

egrep 'abc|xyz' file1 file2 ..filen 
6
Sarath Chandra

これは ack で簡単にできます:

ack -l 'cats' | ack -xl 'dogs'
  • -l:ファイルのリストを返します
  • -x:STDIN(前の検索)からファイルを取得し、それらのファイルのみを検索します

そして、必要なファイルだけを取得するまで、パイピングを続けることができます。

5
Ben Johnson
awk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print "0" }' 

その後、シェルで戻り値をキャッチできます

ruby(1.9+)をお持ちの場合

Ruby -0777 -ne 'print if /Dansk/ and /Norsk/ and /Svenka/' file
4
kurumi

単に:

grep 'Word1\|Word2\|Word3' *

詳細は この投稿 をご覧ください

3
moshe beeri

これは、グレンジャックマンの回答とクルミの回答を組み合わせたもので、任意の数の固定単語または固定の正規表現セットではなく、任意の数の正規表現を許可します。

#!/usr/bin/awk -f
# by Dennis Williamson - 2011-01-25

BEGIN {
    for (i=ARGC-2; i>=1; i--) {
        patterns[ARGV[i]] = 0;
        delete ARGV[i];
    }
}

{
    for (p in patterns)
        if ($0 ~ p)
            matches[p] = 1
            # print    # the matching line could be printed
}

END {
    for (p in patterns) {
        if (matches[p] != 1)
            exit 1
    }
}

次のように実行します。

./multigrep.awk Dansk Norsk Svenska 'Language: .. - A.*c' dvdfile.dat
2

@kurumiのawkの答えを拡張して、bash関数を以下に示します。

all_Word_search() {
    gawk '
        BEGIN {
            for (i=ARGC-2; i>=1; i--) {
                search_terms[ARGV[i]] = 0;
                ARGV[i] = ARGV[i+1];
                delete ARGV[i+1];
            }
        }
        {
            for (i=1;i<=NF; i++) 
                if ($i in search_terms) 
                    search_terms[$1] = 1
        }
        END {
            for (Word in search_terms) 
                if (search_terms[Word] == 0) 
                    exit 1
        }
    ' "$@"
    return $?
}

使用法:

if all_Word_search Dansk Norsk Svenska filename; then
    echo "all words found"
else
    echo "not all words found"
fi
1
glenn jackman

これが私にとってうまくいったものです:

find . -path '*/.svn' -Prune -o -type f -exec gawk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print FILENAME }' {} \;
./path/to/file1.sh
./another/path/to/file2.txt
./blah/foo.php

これら3つの.shファイルを見つけたいだけなら、次のように使用できます。

find . -path '*/.svn' -Prune -o -type f -name "*.sh" -exec gawk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print FILENAME }' {} \;
./path/to/file1.sh
1
Nick Henry

私は2つのステップでそれをしました。 1つのファイルにcsvファイルのリストを作成するこのページのコメントを参考にして、必要なものを取得するために2つのスクリプトレスのステップを作成しました。ターミナルに入力するだけです:

$ find /csv/file/dir -name '*.csv' > csv_list.txt
$ grep -q Svenska `cat csv_list.txt` && grep -q Norsk `cat csv_list.txt` && grep -l Dansk `cat csv_list.txt`

それはまさに私が必要としていたことです-3つの単語すべてを含むファイル名を出力します。

`' "のような記号にも注意してください

1
Simas

今日、この問題が発生しました。ファイルの名前にスペースが含まれていたため、ここのすべてのワンライナーは失敗しました。

これは私が思いついたものです:

grep -ril <Word1> | sed 's/.*/"&"/' | xargs grep -il <Word2>
0
giusti

2つの検索語のみが必要な場合、おそらく最も読みやすいアプローチは、各検索を実行し、結果を交差させることです。

 comm -12 <(grep -rl Word1 . | sort) <(grep -rl Word2 . | sort)
0
Ankur Dave