web-dev-qa-db-fra.com

Grep peut-il afficher uniquement les mots correspondant au modèle de recherche?

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?

539
Neil Baldwin

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.
740
Dan Midwood

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

75
PicoCreator

Vous pouvez traduire des espaces en nouvelles lignes, puis grep, par exemple:

cat * | tr ' ' '\n' | grep th
39
Adam Rosenfield

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
33
ghostdog74

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.
17
Abhinandan prasad

commande grep pour la correspondance et Perl uniquement

grep -o -P 'th.*? ' filename
10
Raghu

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
8
Beau
cat *-text-file | grep -Eio "th[a-z]+"
8
Mumbling Mac

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
4
Sandeep

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
3
Maciek Sawicki

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
3
keebOo

ripgrep

Voici l'exemple utilisant ripgrep:

rg -o "(\w+)?th(\w+)?"

Cela correspond à tous les mots correspondant à th.

0
kenorb
$ 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.

0
pl1nk