grep --before-context 5
mostra 5 righe prima della partita.
Voglio mostrare tutto prima della partita.
Fare grep --before-context 99999999
funzionerebbe ma non è molto ... professionale.
Come mostrare tutti i file fino alla partita?
grep --before-context 5
mostra 5 righe prima della partita.
Voglio mostrare tutto prima della partita.
Fare grep --before-context 99999999
funzionerebbe ma non è molto ... professionale.
Come mostrare tutti i file fino alla partita?
Risposte:
Sed è meglio per questo.
Basta fare:
sed '/PATTERN/q' FILE
Funziona così:
Per ogni riga, osserviamo se corrisponde /PATTERN
:
Questa è la soluzione più efficiente, perché appena vede PATTERN
si chiude. Senza q
, sed continuerebbe a leggere il resto del file e non farebbe nulla con esso. Per file di grandi dimensioni può fare la differenza.
Questo trucco può anche essere usato per emulare head
:
sed 10q FILE
sed '/PATTERN/Q' FILE
salterà la linea corrispondente. Q
è un'estensione GNU, quindi non funzionerà con nessun sed.
sed
può sostituire la maggior parte delle funzionalità di grep.
sed -n '1,/<pattern>/ p' <file>
Questo significa stampare dalla prima riga fino a quando il motivo non viene abbinato.
Un paio di esempi di gamma
sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2
stampa fino alla partita inclusa:
awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename
stampa fino a MA NON compresa la corrispondenza:
awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename
Q
E 'bello ma specifico per gli gnu, sed -n '/pattern/!p;//q'
sarebbe più portatile.
!
che p
valga per le linee che non corrispondono pattern
, ma poi //q
mi confonde ...
//
significa "espressione regolare precedente" (ho pensato che significasse "corrisponde alla stringa vuota"). Penso che una versione più breve della stessa soluzione sia sed -n '/pattern/q;p
:?
I seguenti grep
metodi GNU puri non sono efficienti.
Cerca tutto fino alla prima istanza della stringa " pippo " nella barra dei file , usando tre grep
s:
grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar
Corrispondenza fino all'ultima istanza di " pippo ":
grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar
Nota: i dettagli sull'ultimo grep
sono disponibili in: Regex (grep) per la ricerca su più righe necessaria .
grep
s (+ pcre) quando si tratta semplicemente di eseguire una singola sed
chiamata: sed 'x;/./G;//!x;/foo/p;//s/.*//;x;d'
??
sed
codice sembra valere la sua risposta o potrebbe essere aggiunto a uno degli altri. Ri 7 grep
s: Perché non c'era una grep
risposta ... (in più, la risposta aiuta a mostrare perché no.)
Aggiungendo alla risposta di Mikel sopra ...
Per stampare tutte le righe fino a, ma non includere , la prima riga in FILE
contenimento PATTERN
, provare:
sed '/.*PATTERN.*/{s///;q;}' FILE
Questo corrisponde all'intera riga contenente il modello, lo sostituisce con una riga vuota, quindi si chiude senza elaborare il resto del file.
Post-script:
Il modo più semplice / chiaro a cui potevo pensare per evitare di stampare una nuova riga alla fine (senza coinvolgere un altro strumento), era di eseguire di nuovo sed ed eliminare la nuova riga finale:
sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'
... e dal momento che stiamo eliminando comunque quella linea, il nostro lavoro precedente è ridondante e possiamo semplificare per:
sed '/PATTERN/q' FILE | sed '$d'
sed
invocazione.
tcsh
che in bash
alias, dovevo assicurarmi di aveva una soluzione a una riga relativamente concisa che funzionava sia in standard che GNU sed
(per portabilità); tutti i requisiti che il tuo contributo potrebbe aver soddisfatto. Come qualcuno che usa sed
molto raramente, il mio requisito più importante era qualcosa che potevo capire rapidamente quando volevo modificarlo o riutilizzarlo facilmente tra anni.
Per le persone che scelgono di ricordare solo gli strumenti di base nel lavoro quotidiano e disposti ad accettare soluzioni meno eleganti e meno efficienti:
head -n $(grep -n pattern filename | cut -d: -f1) filename
Se questo comando è per uno script, cercherò soluzioni più eleganti (e possibilmente efficienti). Se questo è un comando una tantum o uno script usa e getta, non mi interessa.
È inoltre possibile utilizzare uno dei seguenti
tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac
o
tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac
o
tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac
La prima opzione è molto simile a quella suggerita dall'OP, ma assicura che ti mostri abbastanza righe prima del contesto contando le righe nel file
La seconda opzione cerca il numero di riga della prima corrispondenza (puoi cambiarlo anche cambiando la 'testa' interna) e quindi usa la testa su quel numero
L'ultima opzione sostituisce tutte le nuove linee con la corrispondenza e quindi sostituisce due partite adiacenti con una nuova linea. L'output di questo è una riga per ogni blocco di testo tra due corrispondenze. Dopodiché usa 'head' per scegliere la prima riga (che comprende il blocco di testo fino alla prima corrispondenza) e che ritrasforma ogni corrispondenza in una nuova riga. questa opzione funziona solo se il file è nel seguente formato
pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern
texttexttext
texttexttexttexttexttexttexttexttext
e così via
sed
comando in fondo è un po 'nodoso.