Je cherche un moyen de rechercher des fichiers où deux instances de mot existent dans le même fichier. J'ai utilisé ce qui suit pour effectuer mes recherches jusqu'à présent:
find . -exec grep -l "FIND ME" {} \;
Le problème que je rencontre est que s'il n'y a pas exactement un espace entre "FIND" et "ME", le résultat de la recherche ne donne pas le fichier. Comment puis-je adapter l'ancienne chaîne de recherche où les mots "FIND" et "ME existent dans un fichier par opposition à" FIND ME "?
J'utilise AIX.
grep -E
/egrep
qui décrit tous les modèles qui vous intéressent (et à utiliser+
au lieu de;
si votre recherche est prise en charge+
.Réponses:
Avec les outils GNU:
Vous pouvez faire de façon standard:
Mais cela exécuterait deux greps par fichier. Pour éviter d'exécuter autant de
grep
s tout en restant portable tout en autorisant tout caractère dans les noms de fichiers, vous pouvez faire:L'idée étant de convertir la sortie de
find
dans un format adapté aux xargs (qui attend un blanc (SPC / TAB / NL, et les autres blancs de votre environnement local avec quelques implémentations dexargs
)) liste séparée de mots où les guillemets simples, doubles et les contre-obliques peuvent échapper aux blancs et les uns aux autres).En règle générale, vous ne pouvez pas post-traiter la sortie de
find -print
, car elle sépare les noms de fichier par un caractère de nouvelle ligne et n'échappe pas aux caractères de nouvelle ligne qui se trouvent dans les noms de fichier. Par exemple, si nous voyons:Nous n'avons aucun moyen de savoir s'il s'agit d'un fichier appelé
b
dans un répertoire appeléa<NL>.
ou s'il s'agit des deux fichiersa
etb
.En utilisant
.//.
, car//
ne peut pas apparaître autrement dans un chemin de fichier en sortie parfind
(car il n'y a pas de répertoire avec un nom vide et/
n'est pas autorisé dans un nom de fichier), nous savons que si nous voyons une ligne qui contient//
, alors c'est la première ligne d'un nouveau nom de fichier. Nous pouvons donc utiliser cetteawk
commande pour échapper à tous les caractères de nouvelle ligne, sauf ceux qui précèdent ces lignes.Si nous prenons l'exemple ci-dessus,
find
sortirait dans le premier cas (un fichier):Quel awk échappe à:
Cela le
xargs
considère donc comme un argument. Et dans le deuxième cas (deux fichiers):Ce qui
awk
resterait tel quel ,xargs
voit donc deux arguments.la source
find ... -print0
et à lagrep --null
place?grep --null
(aka -Z) est utilisé dans le premier mais est une extension GNU.-print0
(une autre extension GNU) n'aiderait pas ici..//.
signifie, et je me demande comment je peux le modifier pour accepter un argument de la ligne de commande, par exemple$1
?-print0
avecfind
et-0
avecxargs
?find -print0
nulle part dans ma réponse.Si les fichiers se trouvent dans un seul répertoire et leur nom ne contiennent pas d' espace, tabulation, nouvelle ligne,
*
,?
ni[
caractères et ne commencent pas par-
ni.
, cela obtenir une liste des fichiers contenant ME, puis réduire que jusqu'à ceux qui contiennent également FIND.la source
grep -l CategoryLinearAxis `grep -l labelJsFunction *`
en recherchant des fichiers qui contiennent les deux attributs. Quelle façon parfaite de le faire. +1Avec
awk
vous pouvez également exécuter:Il utilise
cx
etcy
pour compter les lignes correspondantFIND
et respectivementME
. Dans leEND
bloc, si les deux compteurs> 0, il imprime leFILENAME
.Ce serait plus rapide / plus efficace avec
gnu awk
:la source
Ou utilisez
egrep -e
ougrep -E
aimez ceci:find . -type f -exec egrep -le '(ME.*FIND|FIND.*ME)' {} \;
ou
find . -type f -exec grep -lE '(ME.*FIND|FIND.*ME)' {} +
La commande
+
make find (si elle est prise en charge) ajoute plusieurs noms de fichier (chemin) comme arguments à la commande en cours d'-exec
édition. Cela enregistre les processus et est beaucoup plus rapide que celui\;
qui appelle la commande une fois pour chaque fichier trouvé.-type f
ne correspond qu'aux fichiers, pour éviter de grepping sur un répertoire.'(ME.*FIND|FIND.*ME)'
est une expression régulière correspondant à toute ligne contenant "ME" suivi de "FIND" ou "FIND" suivi de "ME". (guillemets simples pour empêcher le shell d'interpréter des caractères spéciaux).Ajoutez un
-i
à lagrep
commande pour la rendre insensible à la casse.Pour ne faire correspondre que les lignes où "FIND" précède "ME", utilisez
'FIND.*ME'
.Pour exiger des espaces (1 ou plus, mais rien d'autre) entre les mots:
'FIND +ME'
Pour autoriser des espaces (0 ou plus, mais rien d'autre) entre les mots:
'FIND *ME'
Les combinaisons sont infinies avec des expressions régulières, et à condition que vous soyez intéressé à faire des correspondances uniquement ligne par ligne, egrep est très puissant.
la source
find
dans la question.En regardant la réponse acceptée, elle semble plus complexe qu'elle ne devrait l'être. Versions GNU de
find
etgrep
etxargs
support des chaînes terminées par NULL. C'est aussi simple que:Vous pouvez modifier votre
find
commande pour filtrer sur les fichiers que vous souhaitez, et cela fonctionne avec les noms de fichiers contenant n'importe quel caractère; sans la complexité supplémentaire de l'sed
analyse. Si vous souhaitez poursuivre le traitement des fichiers, ajoutez-en un autre--null
au derniergrep
Et, en fonction:
Évidemment, utilisez la réponse acceptée si vous n'exécutez pas de versions GNU de ces outils.
la source
--null
,--print0
,-0
Sont toutes les extensions GNU. Bien que certains d'entre eux se trouvent dans d'autres implémentations de nos jours, ils ne sont toujours pas portables et ne sont pas dans la norme POSIX ou Unix.