2013-07-07 23 views
72

Voglio prendere gli ultimi due numeri (uno int, uno mobile, seguito da spazi bianchi facoltativi) e stamparli solo.sed: stampa solo gruppo corrispondente

Esempio:

foo bar <foo> bla 1 2 3.4 

deve stampare:

2 3.4 

Finora, ho il seguente:

sed -n 's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/replacement/p' 

mi darà

foo bar <foo> bla 1 replacement 

Tuttavia, se provo a sostituirlo con il gruppo 1, viene stampata l'intera riga.

sed -n 's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/\1/p' 

Come posso stampare solo la sezione della linea che corrisponde alla regex nel gruppo?

risposta

80

Abbina l'intera linea, quindi aggiungi un .* all'inizio della tua espressione regolare. Ciò causa l'intera linea per essere sostituito con il contenuto del gruppo

echo "foo bar <foo> bla 1 2 3.4" | 
sed -n 's/.*\([0-9][0-9]*[\ \t][0-9.]*[ \t]*$\)/\1/p' 
2 3.4 
+24

Ho dovuto aggiungere l'opzione '-r' o' --regexp-extended', altrimenti ricevevo l'errore 'reference reference \ 1 on 's' RHS ' error '. –

+9

@DanielSokolowski Penso che tu riceva questo errore se usi '(' e ')' invece di '\ (' e '\)'. –

+1

Ricorda inoltre di aggiungere '.* 'alla fine della regexp se la stringa che vuoi estrarre non è sempre alla fine della riga. –

45

grep è lo strumento giusto per l'estrazione.

utilizzando il vostro esempio e la vostra espressione regolare:

kent$ echo 'foo bar <foo> bla 1 2 3.4'|grep -o '[0-9][0-9]*[\ \t][0-9.]*[\ \t]*$' 
2 3.4 
+0

@jozxyqk il tuo punto è? – Kent

+6

ottimo per l'intero gruppo, sebbene [sed sia necessario per i singoli gruppi] (http://superuser.com/questions/11130/can-gnu-grep-output-a-selected-group) – jozxyqk

+0

grep -o non porta su sistemi che eseguono msysgit ma sed fa. – cchamberlain

7

E per ancora un'altra opzione, mi piacerebbe andare con awk!

echo "foo bar <foo> bla 1 2 3.4" | awk '{ print $(NF-1), $NF; }' 

Questo sarà diviso l'ingresso (sto usando STDIN qui, ma l'input potrebbe facilmente essere un file) sugli spazi, e quindi stampare l'ultimo, ma un campo, e poi l'ultimo campo. Le variabili $NF contengono il numero di campi trovati dopo l'esplosione sugli spazi.

Il vantaggio di questo è che non importa se ciò che precede gli ultimi due campi cambia, purché tu voglia solo gli ultimi due continui a funzionare.

0

Il comando di taglio è progettato per questa situazione esatta. Si "taglia" su qualsiasi delimitatore e quindi è possibile specificare quali blocchi devono essere emessi.

Per esempio: echo "foo bar <foo> bla 1 2 3.4" | cut -d " " -f 6-7

si tradurrà in uscita: 2 3.4

-d imposta il delimitatore

-f seleziona la gamma dei 'campi' a uscita, in questo caso è dal sesto al settimo frammento della stringa originale.

Problemi correlati