2009-11-20 11 views
8

ho visto dallaCome usare sed per restituire qualcosa dalla prima riga che corrisponde e chiude in anticipo?

How to use sed to replace only the first occurrence in a file?

Come fare la maggior parte di ciò che voglio:

sed -n '0,/.*\(something\).*/s//\1/p' 

questo trova la prima partita di qualcosa ed estratti (ovviamente il mio vero esempio è più complicato) . So che sed ha un comando di 'smettere' che lo farà smettere presto, ma non so come combinare la 'q' con la linea sopra per ottenere il mio comportamento desiderato.

Ho provato a sostituire la 'p' con {p; q;} come ho visto in alcuni esempi, ma chiaramente non funziona.

+0

Puoi mostrare più di quello che stai ricevendo e cosa vuoi e in che modo differiscono? Ho fatto "echo -e" aaa 111 aaa \ nbbb 111 bbb "| sed -n '0, /. * \ (111 \). */S // \ 1/p'' e ne ho ottenuto uno" 111 ". Poi ho fatto "echo -e" aaa 111 aaa \ nbbb 111 bbb "| sed -n '0,/\ (. * \ (111 \). * \)/S // \ 1/p'' per mostrare il linea completa per assicurarsi quello che stava ottenendo e ha prodotto "aaa 111 aaa" che è quello che mi aspettavo. Si noti che non sto usando un 'q'. Com'è che "non funziona" per te. –

+0

Il metodo genera l'output corretto, ma continua a elaborare l'intero file anche se non c'è più lavoro da fare, il che è terribile per i file giganti o quando viene utilizzato in una pipeline.Il mio caso d'uso specifico era di scoprire tramite 'git log' su un albero importato git-p4 che era stato usato per l'ultimo commit. git log (quando chiamato senza -n registrerà ogni commit che è accaduto (centinaia di migliaia per me). Non possiamo sapere a priori quale valore dare git per '-n.' La mia soluzione era: log git | sed -n '0, /. * \ [git-p4:. * \/\/depot \/blah \/\ ([^ \ /] * \) \ /.*/ s // \ 1/p;/\ [git-p4/q ' – nosatalian

risposta

3

Il mio caso uso specifico è stato quello di scoprire via 'git log' su un albero importato git-p4 che per forza ramo è stato utilizzato per l'ultima commit. git log (quando chiamato senza -n registrerà ogni commit che è successo (centinaia di migliaia per me)).

Non possiamo sapere a priori quale valore dare a git per "-n". Dopo aver postato questo, ho trovato la mia soluzione che era:

git log | sed -n '0,/.*\[git-p4:.*\/\/depot\/blah\/\([^\/]*\)\/.*/s//\1/p; /\[git-p4/ q' 

mi piace ancora di sapere come fare questo con un non '/' di separazione, e senza dover specificare la parte 'git-p4' due volte , una volta per l'estrazione e una volta per il quit. Deve esserci un modo per combinare entrambi sulla stessa linea ...

1

Sed di solito ha un'opzione per specificare più di un modello da eseguire (IIRC, è l'opzione -e). In questo modo, puoi specificare un secondo modello che si chiude dopo la prima riga.

Un altro approccio consiste nell'utilizzare sed per estrarre la prima riga (sed '1q'), quindi collegarlo a un secondo comando sed (cosa viene mostrato sopra).

1

uso gawk

gawk '/MATCH/{ 
      print "do something with "$0 
      exit 
}' file 
9

Il trucco "stampa e abbandona" funziona, se si mette anche il comando di sostituzione nel blocco (invece di mettere solo la stampa e uscire lì).

Prova:

sed -n '/.*\(something\).*/{s//\1/p;q}' 

Leggi questo tipo: Partita per il modello dato tra le barre. Se questo modello viene trovato, eseguire le azioni specificate nel blocco: Sostituisci, stampa e esci. Tipicamente, i modelli di corrispondenza e sostituzione sono uguali, ma questo non è richiesto, quindi il comando 's' potrebbe anche contenere un RE differente.

In realtà, questo è abbastanza simile a quello che ghostdog74 ha risposto per gawk.

+0

OpenBSD richiede un punto e virgola dopo il comando quit ('q'). –

Problemi correlati