J'ai besoin de trouver des fichiers où une chaîne spécifique apparaît deux fois ou plus.
Par exemple, pour trois fichiers:
Fichier 1:
Hello World!
Fichier 2:
Hello World!
Hello !
Fichier 3:
Hello World!
Hello
Hello Again.
-
Je veux grep Hello
et ne récupérer que les fichiers 2
& 3
.
Et ça:
grep -o -c Hello * | awk -F: '{if ($2 > 1){print $1}}'
Étant donné que la question est étiquetée grep
, voici une solution utilisant uniquement cet utilitaire et bash
(aucune awk
requise):
#!/bin/bash
for file in *
do
if [ "$(grep -c "Hello" "${file}")" -gt 1 ]
then
echo "${file}"
fi
done
Peut être un one-liner:
for file in *; do if [ "$(grep -c "Hello" "${file}")" -gt 1 ]; then echo "${file}"; fi; done
for file in *
avec l’extension de shell souhaitée pour obtenir tous les fichiers de données.grep -c
renvoie le nombre de lignes correspondant au modèle, avec plusieurs correspondances sur une ligne comptant toujours pour une seule ligne correspondante.if [ ... -gt 1 ]
vérifie que plusieurs lignes correspondent dans le fichier. Si c'est le cas:echo ${file}
affiche le nom du fichier.Après avoir lu votre question, je pense que vous souhaitez également rechercher l’affaire hello hello
sur une ligne. (find files where a specific string appears twice or more.
) alors je viens avec ce one-liner:
awk -v p="hello" 'FNR==1{x=0}{x+=gsub(p,p);if(x>1){print FILENAME;nextfile}}' *
p
est le motif que vous souhaitez rechercherUn petit test:
kent$ head f*
==> f <==
hello hello world
==> f2 <==
hello
==> f3 <==
hello
hello
SK-Arch 22:27:00 /tmp/test
kent$ awk -v p="hello" 'FNR==1{x=0}{x+=gsub(p,p);if(x>1){print FILENAME;nextfile}}' f*
f
f3
Cette awk
imprimera le nom de tous les fichiers avec 2
ou plus Hello
awk 'FNR==1 {if (a>1) print f;a=0} /Hello/ {a++} {f=FILENAME} END {if (a>1) print f}' *
file2
file3
Ce dont vous avez besoin est une variable grep
capable de reconnaître les motifs entre les fins de ligne ( "bonjour" suivie de tout (éventuellement de fins de ligne), suivie de "bonjour" )
Étant donné que grep
traite vos fichiers ligne par ligne, il n’est pas (en lui-même) le bon outil pour le travail - sauf si vous parvenez à regrouper l’ensemble du fichier en une seule ligne.
Maintenant, c'est facile, par exemple, en utilisant la commande tr
, en remplaçant les fins de ligne par des espaces:
if cat $file | tr '\n' ' ' | grep -q 'hello.*hello'
then
echo "$file matches"
fi
Ceci est très efficace, même sur des fichiers volumineux comportant beaucoup (par exemple 100 000) lignes, et peut être encore plus efficace en appelant grep
avec --max-count=1
, ce qui permet d’arrêter la recherche après la recherche d’une correspondance. Peu importe que les deux bonjours soient sur la même ligne ou non.
grep -c Bonjour * | egrep -v ': [01] $' | sed 's /: [0-9] * $ //'
Autrement:
grep Hello * | cut -d: -f1 | uniq -d
Grep pour les lignes contenant 'Hello'; ne garder que les noms de fichiers; n'imprimez que les doublons.