Question Grep peut-il afficher uniquement les mots qui correspondent au modèle de recherche?


Existe-t-il un moyen de rendre les «mots» de sortie grep à partir de fichiers qui correspondent à 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 la sortie sera quelque chose comme (gras est par moi);

un fichier texte: la chat assis sur la tapis
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 produise, en utilisant la même recherche, est:

the
the
the
this
thoroughly

Est-ce possible en utilisant grep? Ou en utilisant une autre combinaison d'outils?


486
2017-10-10 00:47


origine


Réponses:


Essayez grep -o

grep -oh "\w*th\w*" *

Edit: correspondance du 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.

651
2017-10-10 01:01



Réponses sécurisées pour 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'inclut pas l'option -o. Utilisez ce qui précède. Sinon, utilisez le plus simple pour maintenir la version ci-dessous.

Distribution croisée Linux réponse sûre

grep -oh "[[:alpha:]]*th[[:alpha:]]*" 'filename'

Pour résumer -oh affiche que l'expression régulière correspond au contenu du fichier (et non à son nom de fichier), tout comme vous vous attendez à ce qu'une expression régulière fonctionne dans vim / etc ... Quel mot ou quelle expression régulière recherchez-vous? Tant que vous restez à la syntaxe POSIX et non perl (voir ci-dessous)

Plus du manuel pour 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 originale ne fonctionne pas pour tout le monde

L'utilisation de \w varie d'une plateforme à l'autre, car c'est une syntaxe "perl" étendue. En tant que tel, ces installations grep qui est limitée à travailler avec les classes de caractères POSIX utilise [[:alpha:]] et non son équivalent de perl de \w. Voir la page Wikipedia sur l'expression régulière pour plus

En fin de compte, la réponse POSIX ci-dessus sera beaucoup plus fiable quelle que soit la plate-forme (étant l'original) pour grep

En ce qui concerne la prise en charge de grep sans l'option -o, le premier grep affiche les lignes appropriées, le tr divise les espaces en nouvelles lignes, le dernier grep ne filtre que pour les lignes respectives.

(PS: Je sais que la plupart des plates-formes ont été corrigées pour \ w .... mais il y a toujours celles qui sont à la traîne)

Crédit pour la solution de contournement "-o" de la réponse @AdamRosenfield


71
2018-04-14 08:17



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

cat * | tr ' ' '\n' | grep th

39
2017-10-10 01:43



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

30
2017-10-10 00:54



commande grep pour seulement correspondance et perl

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

10
2017-11-29 09:11



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.

10
2018-03-28 09:25



J'étais insatisfait de la syntaxe de awk, difficile à retenir, mais j'aimais bien 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 le --output drapeau pour faire cela pour des recherches plus complexes avec à peu près la syntaxe la plus facile que j'ai trouvé:

# 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
2018-01-11 21:25



cat *-text-file | grep -Eio "th[a-z]+"

6
2017-09-14 15:30



Pour rechercher tous les mots commençant par "icône", la commande suivante fonctionne parfaitement. j'utilise Ackici qui est similaire à grep mais avec de meilleures options et un formatage agréable.

ack -oh --type=html "\w*icon-\w*" | sort | uniq

4
2018-01-16 15:46



Vous pouvez aussi essayer pcregrep. Il y a aussi -w option dans grep, mais dans certains cas cela ne fonctionne pas comme prévu.

De Wikipédia:

cat fruitlist.txt
apple
apples
pineapple
apple-
apple-fruit
fruit-apple

grep -w apple fruitlist.txt
apple
apple-
apple-fruit
fruit-apple

3
2017-11-14 12:15



J'ai eu un problème similaire, en recherchant grep / pattern regex et le "motif trouvé trouvé" en sortie.

A la fin j'ai utilisé egrep (même regex sur grep -e ou -G ne m'a pas donné le même résultat de egrep) avec l'option -o

donc, je pense que cela pourrait être quelque chose de similaire à (je ne suis pas un maître de regex):

egrep -o "the*|this{1}|thoroughly{1}" filename

3
2018-02-14 16:39