任意の行にDansk
、Svenska
、または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行で実行できますか?
次を使用できます。
grep -l Dansk * | xargs grep -l Norsk | xargs grep -l Svenska
隠しファイルも検索したい場合:
grep -l Dansk .* | xargs grep -l Norsk | xargs grep -l Svenska
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;完了
grep –irl Word1 * | grep –il Word2 `cat -` | grep –il Word3 `cat -`
-i
は大文字と小文字を区別せずに検索します-r
ファイル検索をフォルダー全体に再帰的にします-l
見つかったWordでファイルのリストをパイプしますcat -
は、次のgrepにリストに渡されたファイルを調べさせます。異なる行のファイル内の複数の文字列をgrepする方法(パイプ記号を使用):
for file in *;do
test $(grep -E 'Dansk|Norsk|Svenska' $file | wc -l) -ge 3 && echo $file
done
ノート:
二重引用符を使用する場合""
をgrepで使用すると、次のようにパイプをエスケープする必要があります:\|
Dansk、Norsk、Svenskaを検索します。
1行に言語が1つしかないと仮定します。
チュートリアル: http://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/
これは、複数のファイルで複数の単語を検索します。
egrep 'abc|xyz' file1 file2 ..filen
これは ack で簡単にできます:
ack -l 'cats' | ack -xl 'dogs'
-l
:ファイルのリストを返します-x
:STDIN(前の検索)からファイルを取得し、それらのファイルのみを検索しますそして、必要なファイルだけを取得するまで、パイピングを続けることができます。
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
これは、グレンジャックマンの回答とクルミの回答を組み合わせたもので、任意の数の固定単語または固定の正規表現セットではなく、任意の数の正規表現を許可します。
#!/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
@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
これが私にとってうまくいったものです:
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
私は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つの単語すべてを含むファイル名を出力します。
`' "
のような記号にも注意してください
今日、この問題が発生しました。ファイルの名前にスペースが含まれていたため、ここのすべてのワンライナーは失敗しました。
これは私が思いついたものです:
grep -ril <Word1> | sed 's/.*/"&"/' | xargs grep -il <Word2>
2つの検索語のみが必要な場合、おそらく最も読みやすいアプローチは、各検索を実行し、結果を交差させることです。
comm -12 <(grep -rl Word1 . | sort) <(grep -rl Word2 . | sort)