2009-11-03 14 views
62

Come è possibile creare linee di corrispondenza del filtro sed in base ad alcune espressioni, ma ignorare le righe non corrispondenti, invece di lasciarle stampare?Sono ignorare le righe non corrispondenti

Come esempio reale, voglio eseguire scalac (il compilatore Scala) su un set di file e leggere dal suo output -verbose i file .class creati. scalac -verbose emette un sacco di messaggi, ma siamo interessati solo a quelli del modulo [wrote some-class-name.class]. Quello che sto facendo attualmente è presente (|& è il modo bash 4.0 di stderr pipe al programma successivo):

$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/' 

Questo estrarrà i nomi dei file dai messaggi che ci interessa, ma sarà anche lasciare che tutti gli altri messaggi passino invariati! Naturalmente potremmo fare invece questo:

$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' | 
    sed 's/^\[wrote \(.*\.class\)\]$/\1/' 

che funziona ma è molto simile in giro per il problema reale, che è il modo di istruire sed di ignorare le linee non corrispondenti dall'ingresso. Quindi come lo facciamo?

risposta

65

Un altro modo semplice con sed:

sed -e 's/.../.../;t;d' 

s/// è un substituion, t senza alcuna etichetta condizionalmente salta tutto seguenti comandi, d cancella linea.

Nessuna necessità di perl o di grep.

(a cura dopo il suggerimento di Nicholas Riley)

+3

Su OS X 10.8.2 ho dovuto separare 'tx' e' d' con una nuova riga piuttosto che un punto e virgola mentre ricevevo l'etichetta non definita 'x; d;: x''. – davidchambers

+4

Ancora meglio: 'sed -e 's /.../.../' -e 'tx' -e 'd' -e ': x'' (suggerito in un commento su una [domanda simile] (http : //stackoverflow.com/a/1252191/312785)). – davidchambers

+1

't' trasferirà alla fine dello script se non viene fornita un'etichetta, in modo più semplice: 'sed -e 's /.../.../' -e 't' -e 'd''. –

3

Uso Perl:

... |& perl -ne 'print "$1\n" if /^\[wrote (.*\.class)\]$/' 
164

Se non si desidera stampare le linee che non corrispondono, è possibile utilizzare la combinazione di

  • -n opzione che indica a sed di non stampare
  • p bandiera che indica a sed di stampare ciò che è abbinato

Questo dà:

sed -n 's/.../.../p' 
+7

Questa dovrebbe essere la risposta accettata –

+1

Uno svantaggio di questo approccio è che se si dispone di più espressioni che corrispondono, il risultato sarà anche stampato più volte. Ad esempio: 'echo foo | sed -n -e 's/foo/bar/p' -e 's/bar/oof/p'' produrrà sia 'bar' che' oof' su righe separate. Sebbene la varietà goto-label non sia in grado di gestire più modelli, poiché eliminerà la riga se il primo modello non corrisponde. – Rapsey

Problemi correlati