web-dev-qa-db-fra.com

Pourquoi l'ancrage de fin de ligne est-il ne travaillant pas avec la commande Grep, même si l'ancrage de première ligne est?

Très nouveau à UNIX mais pas nouveau à la programmation. Utilisation de la borne sur MacBook. Aux fins de la gestion et de la recherche de listes de mots pour la construction de mots croisés, j'essaie d'être utile avec la commande Grep et ses variations. Semble assez simple mais se remettez tôt avec ce que je pensais être un cas simple.

Quand j'entre

grep "^COW" masternospaces.txt

Je reçois ce que je veux: une liste de tous les mots commençant par la vache.

Mais quand j'entre

grep "COW$" masternospaces.txt

Je m'attends à obtenir une liste de mots se terminant par une vache (il y a beaucoup de tels mots), et rien n'est retourné du tout.

Le fichier est un fichier texte brut, avec chaque ligne juste un mot (ou une phrase de mots sans espaces) dans toutes les capsules.

Avez-vous une idée de ce qui pourrait arriver ici?

20
DTalvacchio

Comme @steeldiver mentionné, le problème est susceptible d'être causé par un style de fin de ligne différent de ce que grep s'attend à.

Pour vérifier les terminaisons de ligne

Vous pouvez utiliser hexdump pour vérifier exactement comment vos fins de ligne sont formatées. Je vous suggère d'utiliser mon format préféré:

hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt

Avec la sortie, vérifiez les terminaisons de ligne: 0a -> LF, 0d -> CR. Un exemple très rapide donnerait quelque chose comme ça:

$ hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt
00000000 (0x00000000)    4e 6f 20 43 4f 57 20 65   6e 64 69 6e 67 0d 0a 45    No COW e|nding..E
00000016 (0x00000010)    6e 64 69 6e 67 20 69 6e   20 43 4f 57 0d 0a          nding in| COW..

Notez les terminaisons de ligne au format DOS: 0d 0a.

Pour changer les terminaisons de ligne

Vous pouvez voir ici ou ICI Pour diverses méthodes de modification des terminaisons de ligne utilisant divers outils, mais pour une chose unique, vous pouvez toujours utiliser VI/Vim:

vim masternospaces.txt
:set fileformat=unix
:wq

à grep sans changer quoi que ce soit

Si vous voulez juste grep doit correspondre, quelle que soit la ligne de fin, vous pouvez toujours spécifier des terminaisons de ligne telles que ceci:

grep 'COW[[:cntrl:]]*$' masternospaces.txt

Si une ligne vierge est affichée, vous pouvez vérifier que vous avez effectivement assorti quelque chose en utilisant le -v Option de cat:

grep 'COW[[:cntrl:]]*$' masternospaces.txt | cat -v

Mon préféré personnel

Vous pouvez également également grener et standardiser la sortie à l'aide de sed:

sed -n '/COW^M*$/{;s/^M//g;p;};' masternospaces.txt

^M est obtenu en tapant Ctrl-V Ctrl-M sur votre clavier.

J'espère que cela t'aides!

23
user43791

Une autre façon d'enlever le \r avant le grep:

... | dos2unix | egrep 'COW$' | ...

J'aime que c'est très clair puisque je ne me souviens pas de choses comme [[:cntrl:]] pour longtemps.

1
Javier

Bien que vous puissiez utiliser la syntaxe de Regex 'standard' avec Grep (comme dans @ user43791's réponse ), Grep dispose également d'autres identificateurs de signifier les limites d'entrée.

Les correspondants pour le début et la fin de toute la ligne sont \` (backtick) (au lieu de ^) et \' (Apostrophe) (au lieu de $).

Donc, pour votre commande d'origine, vous utiliseriez: grep "COW\'" masternospaces.txt

Note latérale: Il est également important de noter que ? et + sera traité littéralement à moins que vous ne vous échappiez pas en utilisant \? et \+ Pour en faire leurs homologues de sélecteur de style Regex.

Source: grep syntaxe d'expression régulière

1
samthecodingman