Existe-t-il un moyen de créer des "mots" en sortie de grep à partir de fichiers correspondant à l'expression de recherche?
Si je veux trouver toutes les instances de, disons "th" dans un certain nombre de fichiers, je peux faire:
grep "th" *
mais le résultat sera quelque chose comme (gras est par moi);
un-fichier-texte: la chat assis sur la mat un-autre-fichier-texte: la renard brun rapide encore-un-autre-fichier-texte: j'espère ce l'explique complètement
Ce que je veux qu'il affiche, en utilisant la même recherche, est:
the
the
the
this
thoroughly
Est-ce possible d'utiliser grep? Ou en utilisant une autre combinaison d'outils?
Essayez grep -o
grep -oh "\w*th\w*" *
Edit: correspondant au commentaire de Phil
De les docs :
-h, --no-filename
Suppress the prefixing of file names on output. This is the default
when there is only one file (or only standard input) to search.
-o, --only-matching
Print only the matched (non-empty) parts of a matching line,
with each such part on a separate output line.
Réponse sûre à la distribution croisée (y compris windows minGW?)
grep -h "[[:alpha:]]*th[[:alpha:]]*" 'filename' | tr ' ' '\n' | grep -h "[[:alpha:]]*th[[:alpha:]]*"
Si vous utilisez des versions plus anciennes de grep (comme 2.4.2) qui n’incluent pas l’option -o. Utilisez ce qui précède. Sinon utilisez le plus simple de maintenir la version ci-dessous.
Réponse sûre à la distribution croisée Linux
grep -oh "[[:alpha:]]*th[[:alpha:]]*" 'filename'
Pour les résumés, -oh
génère les correspondances d'expression régulière avec le contenu du fichier (et non son nom de fichier), comme si vous vous attendiez à ce que l'expression régulière fonctionne dans vim/etc ... Le mot ou l'expression régulière que vous recherchez alors est actif. à toi! Tant que vous restez à POSIX et non à la syntaxe Perl (voir ci-dessous)
Plus d'informations dans le manuel de grep
-o Print each match, but only the match, not the entire line.
-h Never print filename headers (i.e. filenames) with output lines.
-w The expression is searched for as a Word (as if surrounded by
`[[:<:]]' and `[[:>:]]';
La raison pour laquelle la réponse initiale ne fonctionne pas pour tout le monde
L'utilisation de \w
varie d'une plate-forme à l'autre, car c'est une syntaxe "Perl" étendue. En tant que tel, l'installation de grep limitée au travail avec les classes de caractères POSIX utilise [[:alpha:]]
et non son équivalent Perl de \w
. Voir la page Wikipedia sur l'expression régulière pour plus d'informations
En fin de compte, la réponse POSIX ci-dessus sera bien plus fiable, quelle que soit la plate-forme (la plus originale) pour grep
En ce qui concerne la prise en charge de grep sans l'option -o, le premier grep génère les lignes appropriées, le tr divise les espaces en nouvelles lignes et le filtre final de grep uniquement pour les lignes respectives.
(PS: Je connais maintenant la plupart des plateformes, elles auraient été corrigées pour\w .... mais il y en a toujours qui sont à la traîne)
Crédit pour la solution de contournement "-o" de @AdamRosenfield answer
Vous pouvez traduire des espaces en nouvelles lignes, puis grep, par exemple:
cat * | tr ' ' '\n' | grep th
Juste awk
, pas besoin de combinaison d'outils.
# awk '{for(i=1;i<=NF;i++){if($i~/^th/){print $i}}}' file
the
the
the
this
thoroughly
C'est plus simple que vous ne le pensez. Essaye ça:
egrep -wo 'th.[a-z]*' filename.txt #### (Case Sensitive)
egrep -iwo 'th.[a-z]*' filename.txt ### (Case Insensitive)
Où,
egrep: Grep will work with extended regular expression.
w : Matches only Word/words instead of substring.
o : Display only matched pattern instead of whole line.
i : If u want to ignore case sensitivity.
commande grep pour la correspondance et Perl uniquement
grep -o -P 'th.*? ' filename
J'étais insatisfait de la syntaxe difficile à retenir de awk mais j'aimais l'idée d'utiliser un seul utilitaire pour le faire.
Il semble que ack (ou ack-grep si vous utilisez Ubuntu) peut le faire facilement:
# ack-grep -ho "\bth.*?\b" *
the
the
the
this
thoroughly
Si vous omettez le drapeau -h, vous obtenez:
# ack-grep -o "\bth.*?\b" *
some-other-text-file
1:the
some-text-file
1:the
the
yet-another-text-file
1:this
thoroughly
En prime, vous pouvez utiliser l'indicateur --output
pour effectuer des recherches plus complexes avec la syntaxe la plus simple que j'ai trouvée:
# echo "bug: 1, id: 5, time: 12/27/2010" > test-file
# ack-grep -ho "bug: (\d*), id: (\d*), time: (.*)" --output '$1, $2, $3' test-file
1, 5, 12/27/2010
cat *-text-file | grep -Eio "th[a-z]+"
Pour rechercher tous les mots commençant par "icon-", la commande suivante fonctionne parfaitement. J'utilise Ack ici, ce qui est similaire à grep mais avec de meilleures options et un formatage agréable.
ack -oh --type=html "\w*icon-\w*" | sort | uniq
Vous pouvez également essayer pcregrep. Il existe également une option -w
dans grep, mais dans certains cas, cela ne fonctionne pas comme prévu.
De Wikipedia :
cat fruitlist.txt
Apple
apples
pineapple
Apple-
Apple-fruit
fruit-Apple
grep -w Apple fruitlist.txt
Apple
apple-
Apple-fruit
fruit-Apple
J'ai eu un problème similaire, à la recherche de grep/pattern regex et du "modèle correspondant trouvé" en sortie.
A la fin, j'ai utilisé egrep (même expression régulière sur grep -e ou -G ne m'a pas donné le même résultat d'egrep) avec l'option -o
donc, je pense que cela pourrait être quelque chose de similaire à (je ne suis pas un maître regex):
egrep -o "the*|this{1}|thoroughly{1}" filename
ripgrep
Voici l'exemple utilisant ripgrep
:
rg -o "(\w+)?th(\w+)?"
Cela correspond à tous les mots correspondant à th
.
$ grep -w
Extrait de la page de manuel de grep:
-w: Sélectionnez uniquement les lignes contenant des correspondances qui forment des mots entiers. Le test est que la sous-chaîne correspondante doit être au début de la ligne ou précédée d'un caractère constitutif autre que Word.