Come posso usare il taglio per separare per più spazi bianchi?


23

Vorrei ottenere l'ultima colonna di questo esempio:

[  3]  1.0- 2.0 sec  1.00 MBytes  8.39 Mbits/sec
[  3]  2.0- 3.0 sec   768 KBytes  6.29 Mbits/sec
[  3]  3.0- 4.0 sec   512 KBytes  4.19 Mbits/sec
[  3]  4.0- 5.0 sec   256 KBytes  2.10 Mbits/sec
...

Se io uso

cut -d\  -f 13

ottengo

Mbits/sec
6.29
4.19
2.10

perché a volte ci sono spazi aggiuntivi in ​​mezzo.


L'ultima colonna è Mbits/sec, è quello che vuoi o le ultime 2 colonne?
terdon

1
Voglio solo ottenere la penultima colonna, solo i numeri
rubo77,

Risposte:


17

Per rispondere letteralmente alla tua domanda:

sed 's/   */:/g' | cut -d : -f 5

o

awk -F '  +' '{print $5}'

Ma ciò non funzionerà se il numero tra parentesi raggiunge 10, ecc. Se sei interessato solo ai numeri, puoi rimuovere tutto il resto.

sed 's/[^.0-9][^.0-9]*/:/g' | cut -d : -f 6

sì, certo solo i numeri, ma solo il tuo terzo esempio funziona correttamente
rubo77,

@ rubo77 Funziona per me. I primi due esempi fanno esattamente quello che chiedi nel tuo titolo. O hai voluto spogliare anche l'unità? In tal caso, aggiungere | sed 's/ .*//'alla fine dei primi due esempi. Naturalmente ci sono molti altri modi per farlo.
Gilles 'SO- smetti di essere malvagio' il

un po 'più corto con +invece di *: cat test | sed 's / [^. 0-9] \ + /: / g' | cut -d: -f 6
rubo77

@ rubo77 Se la tua sed lo supporta, cioè. È supportato da GNU e BusyBox ma non da BSD o Solaris. POSIX specifica +e ?in ERE ma lascia \+e \?in BRE non definito.
Gilles 'SO- smetti di essere malvagio'

22

Se utilizziamo il trcomando insieme all'opzione squeeze ( -sflag) per convertire tutti gli spazi multipli consecutivi in ​​un singolo spazio e quindi eseguiamo l' cutoperazione con lo spazio come delimitatore, possiamo accedere alla colonna richiesta che trasporta i numeri.

Fare riferimento al seguente codice snipped:

cat file | tr -s ' ' | cut -d ' ' -f 8


4
Questa risposta dovrebbe essere più alta; è di gran lunga la soluzione più semplice e più leggibile.
Luke Davis,

5

Tutti questi comandi stamperanno l'ultima colonna di un file separato da spazi:

  • awk '{print $NF}' file

    in awk, NFè il numero di campi ed $NFè l'ultimo campo.

  • perl -lane 'print $F[$#F]' file

    -adivide il file su spazi bianchi nella matrice @F, $#Fè il numero di elementi nella matrice così $F[$#F]è l'ultimo elemento. I -nmezzi leggono il file fornito nella riga di comando e applicano lo script passato con -eciascuna riga. -laggiunge solo un carattere di nuova riga ( \n) a ciascuna printistruzione.

  • sed 's/.* //g'

    una semplice espressione regolare che abbina tutto all'ultimo spazio e lo elimina, lasciando solo l'ultima colonna.

  • rev file | cut -d' ' -f 1 | rev

    revinverte il suo output in modo che l'ultimo campo sia il primo, cutcon spazio delimitatore per stamparlo e revriportare il testo alla normalità. Questo non funzionerà se si dispone di spazi bianchi consecutivi .

Sulla base del tuo contributo, immagino che in realtà non desideri l'ultima colonna ma la penultima o le ultime due. In tal caso, utilizzare questi per stampare gli ultimi 2 ( 8.39 Mbits/sec):

awk '{print $(NF-1),$NF}' file 
perl -lane 'print "$F[$#F-1] $F[$#F]"' file 
sed 's/.* \(.* .*\)/\1/' file 
rev file | cut -d' ' -f 1,2 | rev

e questi per stampare il penultimo ( 8.39):

awk '{print $(NF-1)}' file 
perl -lane 'print $F[$#F-1]' file 
sed 's/.* \(.*\) .*/\1/' file 
rev file | cut -d' ' -f 2 | rev

4

Non è possibile separare più occorrenze di spazi bianchi usando cutcome da manuale:

I campi di output sono separati da una singola occorrenza del carattere delimitatore di campo.

a meno che il testo non sia separato dalla stessa quantità o che tu usi trper rimuoverne l'eccesso.

In caso contrario, utilizzare strumenti alternativi come awk, sedo ex.

Per esempio:

ex -s +'%norm $2Bd0' +%p +q! foo.txt

Sostituisci +q!con -cwqper salvare le modifiche sul posto.


0

Utilizzare un perl one-liner in questo modo:

perl -lane 'print $F[-2]' input_file

Spiegazione:

L'opzione -efa sì che l'interprete perl cerchi lo script in linea, piuttosto che in un file.

L'opzione -nfa sì che l'input (file o STDIN da una pipe) venga letto riga per riga.

L'opzione -lrimuove il separatore del record di input (dipendente dal sistema operativo, newline su UNIX per impostazione predefinita) dopo aver letto la riga e lo aggiunge alla fine di ogniprint

L'opzione -afa in modo che ogni riga di input venga suddivisa su uno spazio bianco in matrice @F, ed $F[-2]è il secondo elemento che conta dalla fine, che è il campo desiderato. Puoi anche usare $F[$#F-1], dove si $#Ftrova l'ultimo indice dell'array @F, che è leggermente meno leggibile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.