Je veux grep pour les fichiers contenant les mots Dansk
, Svenska
ou Norsk
sur une ligne, avec un code de retour utilisable (comme je n'aime vraiment que l'information que les chaînes sont contenues, mon one-liner va un peu plus loin que cela).
J'ai beaucoup de fichiers avec des lignes comme celles-ci:
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,
(...)
Voici le pseudocode de ce que je veux:
for all files in directory;
if file contains "Dansk" AND "Norsk" AND "Svenska" then
then echo the filename
end
Quelle est la meilleure façon de procéder? Cela peut-il être fait sur une seule ligne?
Vous pouvez utiliser:
grep -l Dansk * | xargs grep -l Norsk | xargs grep -l Svenska
Si vous voulez aussi trouver dans des fichiers cachés:
grep -l Dansk .* | xargs grep -l Norsk | xargs grep -l Svenska
Encore une autre façon d’utiliser simplement bash et grep:
Pour un seul fichier 'test.txt':
grep -q Dansk test.txt && grep -q Norsk test.txt && grep -l Svenska test.txt
Imprimera test.txt
si le fichier contient les trois (quelle que soit la combinaison). Les deux premiers greps n'impriment rien (-q
) et le dernier n'imprime le fichier que si les deux autres ont réussi.
Si vous voulez le faire pour chaque fichier du répertoire:
pour f dans *; do grep -q Dansk $ f && grep -q Norsk $ f && grep -l Svenska $ f; terminé
grep –irl Word1 * | grep –il Word2 `cat -` | grep –il Word3 `cat -`
-i
rend la recherche insensible à la casse-r
rend la recherche de fichier récursive dans les dossiers-l
dirige la liste des fichiers avec le mot trouvécat -
amène le prochain grep à parcourir les fichiers qui lui sont transmis.Comment grep pour plusieurs chaînes dans un fichier sur différentes lignes (utilisez le symbole du canal):
for file in *;do
test $(grep -E 'Dansk|Norsk|Svenska' $file | wc -l) -ge 3 && echo $file
done
Remarques:
Si vous utilisez des guillemets ""
avec votre grep, vous devrez vous échapper du tube comme ceci: \|
pour rechercher Dansk, Norsk et Svenska.
Suppose qu'une ligne n'a qu'une seule langue.
Procédure pas à pas: http://www.cyberciti.biz/faq/howto-use-grep-command-in-linux-unix/
Vous pouvez le faire très facilement avec ack :
ack -l 'cats' | ack -xl 'dogs'
-l
: retourne une liste de fichiers -x
: prend les fichiers de STDIN (la recherche précédente) et ne cherche que ces fichiersEt vous pouvez simplement continuer à jouer jusqu'à ce que vous obteniez uniquement les fichiers souhaités.
Ceci recherche plusieurs mots dans plusieurs fichiers:
egrep 'abc|xyz' file1 file2 ..filen
awk '/Dansk/{a=1}/Norsk/{b=1}/Svenska/{c=1}END{ if (a && b && c) print "0" }'
vous pouvez alors attraper la valeur de retour avec le shell
si vous avez Ruby (1.9+)
Ruby -0777 -ne 'print if /Dansk/ and /Norsk/ and /Svenka/' file
Il s'agit d'un mélange de réponses de glenn jackman et de kurumi qui permet un nombre arbitraire de regex au lieu d'un nombre arbitraire de mots fixes ou d'un ensemble fixe de regex.
#!/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
}
}
Exécutez-le comme ça:
./multigrep.awk Dansk Norsk Svenska 'Language: .. - A.*c' dvdfile.dat
En développant la réponse awk de @ kurumi, voici une fonction 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 $?
}
Usage:
if all_Word_search Dansk Norsk Svenska filename; then
echo "all words found"
else
echo "not all words found"
fi
Voici ce qui a bien fonctionné pour moi:
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
Si je voulais juste trouver des fichiers .sh avec ces trois fichiers, j'aurais pu utiliser:
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
Je l'ai fait en deux étapes. Dressez une liste des fichiers csv dans un fichier Avec l’aide de cette page de commentaires, j’ai fait deux étapes sans script pour obtenir ce dont j'avais besoin. Il suffit de taper dans le terminal:
$ 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`
il a fait exactement ce dont j'avais besoin - imprimer les noms de fichiers contenant les trois mots.
Attention aussi aux symboles comme `' "
J'ai eu ce problème aujourd'hui, et tous les monolignes ici ont échoué parce que les fichiers contenaient des espaces dans les noms.
Voici ce que j'ai trouvé qui a fonctionné:
grep -ril <Word1> | sed 's/.*/"&"/' | xargs grep -il <Word2>
Si vous n'avez besoin que de deux termes de recherche, l'approche la plus lisible consiste à lancer chaque recherche et à intersecter les résultats:
comm -12 <(grep -rl Word1 . | sort) <(grep -rl Word2 . | sort)