Perché l'ancora $ end-of-line non funziona con il comando grep, anche se l'ancora ^ front-of-line è?


19

Molto nuovo in UNIX ma non nuovo in programmazione. Utilizzo del terminale su MacBook. Ai fini della gestione e della ricerca di elenchi di parole per la costruzione di parole crociate, sto cercando di familiarizzare con il comando Grep e le sue varianti. Sembra piuttosto semplice, ma essere sospesi presto con quello che pensavo dovesse essere un caso semplice.

Quando entro

grep "^COW" masternospaces.txt

Ottengo quello che voglio: un elenco di tutte le parole che iniziano con COW.

Ma quando entro

grep "COW$" masternospaces.txt

Mi aspetto di ottenere un elenco di parole che terminano con COW (ci sono molte di queste parole) e nulla viene restituito.

Il file è un semplice file di testo, con ogni riga solo una parola (o una frase di parole senza spazi) in maiuscolo.

Qualche idea di cosa potrebbe succedere qui?


3
Qual è l'origine del file masternospaces.txt? è possibile che abbia terminazioni di linea in stile Windows (CR-LF) invece di LF in stile Unix?
Steeldriver,

2
Non sono sicuro, ma stai cercando un elenco di parole o un elenco di righe ... ?
Mikeserv,

steeldriver-- Qualcosa del genere è stato il mio primo pensiero. Non ero sicuro di come ispezionare ciò che stava accadendo lì, o quali fossero anche le possibilità. Supponeva che un ritorno finale fosse un ritorno finale. Quel file è un enorme compendio di poche fonti. Non sono nemmeno sicuro di quale sarebbe considerato il file originale. Ed è passato attraverso almeno tre word processor sia su PC che su macchine Mac. Quale potrebbe essere il modo migliore per vedere che tipo di terminazioni sta usando?
DTalvacchio,

mikeserv-- In questo file .txt, ogni riga è solo una parola (o una frase senza spazi tra le parole, quindi di nuovo una "parola"). Quindi sto cercando delle linee, suppongo. . . solo che ogni riga ha solo uno di ciò che sto prendendo in considerazione una parola per scopi di cruciverba.
DTalvacchio,

1
Puoi utilizzare hexdumpper verificare esattamente come sono formattati i tuoi finali di riga. Vi suggerisco di usare il mio formato preferito: hexdump -e '"%08_ad (0x%08_ax) "8/1 "%02x "" "8/1 "%02x "' -e '" "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt. Con l'output, controllare le terminazioni di riga: 0a-> LF, 0d-> CR.
user43791,

Risposte:


23

Come menzionato @steeldriver, è probabile che il problema sia causato da uno stile di fine linea diverso da quello che ci grepsi aspetta.

Per controllare le terminazioni di linea

Puoi utilizzare hexdumpper verificare esattamente come sono formattati i tuoi finali di riga. Ti suggerisco di usare il mio formato preferito:

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

Con l'output, controllare le terminazioni di riga: 0a-> LF, 0d-> CR. Un esempio molto rapido darebbe qualcosa del genere:

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

Notare i fine riga in formato DOS: 0d 0a.

Per modificare le terminazioni di riga

Puoi vedere qui o qui per vari metodi per cambiare le terminazioni di linea usando vari strumenti, ma per una cosa sola, puoi sempre usare vi / vim:

vim masternospaces.txt
:set fileformat=unix
:wq

Grep senza cambiare nulla

Se desideri solo grepabbinare la fine della linea, puoi sempre specificare la fine della linea in questo modo:

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

Se viene visualizzata una riga vuota, puoi verificare che abbini effettivamente qualcosa usando l' -vopzione di cat:

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

Il mio preferito personale

Puoi anche grep e standardizzare l'output usando sed:

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

dove ^Msi ottiene digitando Ctrl-V Ctrl-Msulla tastiera.

Spero che sia di aiuto!


È tutto estremamente utile. Sono fuori tempo oggi, ma guarderò da vicino tutto questo da vicino e vedremo che cosa. Se nel frattempo qualcuno di voi ha un link alla propria guida di riferimento ai comandi Unix preferita in modo che io possa insegnarmi un po 'su come funzionano le cose, lo apprezzerei. Ho raccolto pezzi qua e là ma devo ancora trovare una fonte che è il mio punto di partenza per le spiegazioni. Grazie a tutti e domani effettueremo il check-in con un aggiornamento che si spera abbia successo. --D
DTalvacchio il

Peccato che questo post non abbia una chiusura, almeno per me. Non riesco, per la mia vita, a capire come abbinare la fine della linea. Se faccio una discarica esadecimale, non trovo una bella linea che finisca come il tuo esempio sopra. Non ho familiarità con il lavoro con hex, quindi potrei non leggerlo nel modo giusto. Ho anche provato il [[:cntrl:]]suggerito @ user43791 e non corrisponde ancora nulla per me. Questo non ha senso. Sto usando GNU grep 2.20 e analizzando l'output di nDPI che è stato scritto in un file di testo
Harperville,

@harperville Se tu cat -v yourfile.ext, cosa vedi?
user43791

Bene, niente di eccitante o inaspettato. Solo i contenuti come mi aspetterei di vederli. Qualcosa di specifico che stai cercando? Non riesco a incollare l'output qui, ma vedo solo il contenuto. "Testo ASCII in inglese" regolare secondo file.
Harperville,

@harperville Nessun extra "^ M" alla fine di ogni riga? Potresti incollare le prime poche righe dell'esagono?
user43791

1

Sebbene sia possibile utilizzare la sintassi RegEx 'standard' con grep (come nella risposta di @ user43791 ), grep ha anche altri identificatori per indicare i limiti di input.

I matcher per l'inizio e la fine di tutta la riga sono \`(backtick) (invece di ^) e \'(apostrofo) (invece di $).

Quindi per il tuo comando originale, useresti: grep "COW\'" masternospaces.txt

Nota a margine: è anche importante notare che ?e +saranno trattati letteralmente a meno che non li sfuggiate usando \?e \+per renderli le loro controparti selettori in stile RegEx.

Fonte: grepsintassi delle espressioni regolari


grep sta prendendo ^ (cursore) per l'inizio e \ '(apostrofo) per fine
GypsyCosmonaut

1

Un altro modo per rimuovere il \rprima del grep:

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

Mi piace che sia molto chiaro poiché non ricordo cose come [[:cntrl:]]a lungo.


-2

"COW $" quando bash ha impostato il pararametro per grep, è stato interpretato come 'COW' dove trattano "$" come "", poiché $ è un simbolo di fuga. quando nulla è stato associato da $, viene interpretato come stringa vuota da bash shell, quindi dovresti usare invece grep 'COW $' masternospaces.txt.


3
dal momento che non esiste una valida espansione di $, sarebbe lasciato solo da bash e utilizzato da grep. Guarda tu stesso: echo "COW$"- ci $sarà ancora.
Jeff Schaller

-3

In BSD grep devi scappare "$" e racchiudere la stringa tra virgolette doppie:

"COW\$"

1
Um ... no. Il $non sarà speciale per la shell, perché la roba dopo che non è un nome di variabile shell valida. L'uso di virgolette singole attorno alle stringhe statiche è un'idea migliore, ma qui non farà alcuna differenza.
Kusalananda
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.