Usando awk
o sed
come posso selezionare le linee che si verificano tra due diversi pattern di marker? Potrebbero esserci più sezioni contrassegnate con questi modelli.
Ad esempio: Supponiamo che il file contenga:
abc def1 ghi1 jkl1 mno abc def2 ghi2 jkl2 mno pqr stu
E il modello iniziale è abc
e il pattern finale è mno
Quindi, ho bisogno dell’output come:
def1 ghi1 jkl1 def2 ghi2 jkl2
Sto usando sed per abbinare il modello una volta:
sed -e '1,/abc/d' -e '/mno/,$d'
C’è un modo in sed
o awk
di farlo ripetutamente fino alla fine del file?
Utilizza awk
con un flag per triggersre la stampa quando necessario:
$ awk '/abc/{flag=1;next}/mno/{flag=0}flag' file def1 ghi1 jkl1 def2 ghi2 jkl2
Come funziona?
/abc/
corrisponde alle righe che hanno questo testo, così come /mno/
does. /abc/{flag=1;next}
imposta il flag
quando viene trovato il testo abc
. Quindi, salta la linea. /mno/{flag=0}
distriggers il flag
quando viene trovato il testo mno
. flag
finale è un pattern con l’azione di default, che è di print $0
: se flag
è uguale a 1 la linea viene stampata. Per una descrizione più dettagliata ed esempi, insieme ai casi in cui i modelli sono mostrati o meno, vedi Come selezionare le linee tra due modelli? .
Usando sed
:
sed -n -e '/^abc$/,/^mno$/{ /^abc$/d; /^mno$/d; p; }'
L’opzione -n
significa che non viene stampata di default.
Il modello cerca le linee che contengono solo abc
appena a mno
, quindi esegue le azioni nel { ... }
. La prima azione cancella la linea abc
; il secondo la linea mno
; e la p
stampa le righe rimanenti. È ansible rilassare le espressioni rege come richiesto. Qualsiasi linea al di fuori del range di abc
.. mno
viene semplicemente stampata.
Questo potrebbe funzionare per te (GNU sed):
sed '/^abc$/,/^mno$/{//!b};d' file
Elimina tutte le righe tranne quelle tra le righe che iniziano con abc
e mno
sed '/^abc$/,/^mno$/!d;//d' file
golf due personaggi meglio di ppotong {//!b};d
Le barre vuote in avanti //
significano: “riusare l’ultima espressione regolare usata”. e il comando fa lo stesso di quello più comprensibile:
sed '/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d' file
Questo sembra essere POSIX :
Se un RE è vuoto (cioè non è specificato alcun modello) sed si comporterà come se fosse stata specificata l’ultima RE utilizzata nell’ultimo comando applicato (come indirizzo o parte di un comando sostitutivo).
Dai link della precedente risposta, quello che ha fatto per me, eseguire ksh su Solaris, era questo:
sed '1,/firstmatch/d;/secondmatch/,$d'
La risposta di Don_crissti da Mostra solo il testo tra 2 pattern di corrispondenza ?
firstmatch="abc" secondmatch="cdf" sed "/$firstmatch/,/$secondmatch/!d;//d" infile
che è molto più efficiente dell’applicazione di AWK, vedi qui .
perl -lne 'print if((/abc/../mno/) && !(/abc/||/mno/))' your_file
qualcosa del genere funziona per me:
file.awk:
BEGIN { record=0 } /^abc$/ { record=1 } /^mno$/ { record=0; print "s="s; s="" } !/^abc|mno$/ { if (record==1) { s = s"\n"$0 } }
utilizzando: awk -f file.awk data
…
modifica: O_o la soluzione fedorqui è decisamente migliore / più carina della mia.