¿Cómo uso cortar para separar por espacios en blanco múltiples?

23

Me gustaría obtener la última columna de esta muestra:

[  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
...

Si yo uso

cut -d\  -f 13

yo obtengo

Mbits/sec
6.29
4.19
2.10

porque a veces hay espacios adicionales en el medio.

rubo77
fuente
La última columna es Mbits/sec, ¿es eso lo que quieres o las 2 últimas columnas?
terdon
1
Solo quiero obtener la 2da última columna, solo los números
rubo77

Respuestas:

17

Para responder a su pregunta literalmente:

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

o

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

Pero eso no funcionará si el número entre paréntesis llega a 10, etc. Si solo le interesan los números, puede eliminar todo lo demás.

sed 's/[^.0-9][^.0-9]*/:/g' | cut -d : -f 6
Gilles 'SO- deja de ser malvado'
fuente
sí, seguro solo los números, pero solo su 3er ejemplo funciona correctamente
rubo77
@ rubo77 Funciona para mí. Los primeros dos ejemplos hacen exactamente lo que pides en tu título. ¿O también querías quitarle la unidad? En ese caso, agregue | sed 's/ .*//'al final de los dos primeros ejemplos. Por supuesto, hay muchas otras formas de hacerlo.
Gilles 'SO- deja de ser malvado'
un poco más corto con en +lugar de *: prueba de gato | sed 's / [^. 0-9] \ + /: / g' | cut -d: -f 6
rubo77
@ rubo77 Si su sed lo soporta, eso es. Es compatible con GNU y BusyBox, pero no con, por ejemplo, BSD o Solaris. POSIX especifica +y ?en ERE pero deja \+y \?en BRE indefinido.
Gilles 'SO- deja de ser malvado'
22

Si usamos el trcomando junto con la opción de compresión ( -sbandera) para convertir todos los espacios consecutivos múltiples en un solo espacio y luego realizar la cutoperación con el espacio como delimitador, podemos acceder a la columna requerida con los números.

Consulte el código recortado a continuación:

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

Wald Schilfrohr
fuente
44
Esta respuesta debería ser mayor; Es, con mucho, la solución más simple y legible.
Luke Davis el
5

Todos estos comandos imprimirán la última columna de un archivo separado por espacios:

  • awk '{print $NF}' file

    en awk, NFes el número de campos y $NFes el último campo.

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

    -adivide el archivo en el espacio en blanco en la matriz @F, $#Fes el número de elementos en la matriz, por lo que $F[$#F]es el último elemento. Los -nmedios leen el archivo dado en la línea de comando y aplican el script pasado con-e a cada línea. -lsimplemente agrega un carácter de nueva línea ( \n) a cada printdeclaración.

  • sed 's/.* //g'

    una expresión regular simple que hace coincidir todo con el último espacio y lo elimina, dejando solo la última columna.

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

    rev invierte su salida para que el último campo sea el primero, cut con espacio delimitador para imprimirlo y revvolver el texto a la normalidad. Esto no funcionará si tiene espacios en blanco consecutivos .

Según su aporte, supongo que en realidad no desea la última columna, sino la penúltima o las dos últimas. En ese caso, utilice estos para imprimir los últimos 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

y estos para imprimir el penúltimo ( 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
terdon
fuente
4

No puede separar la aparición múltiple de espacios en blanco usando cut según el manual:

Los campos de salida están separados por una sola aparición del carácter delimitador de campo.

a menos que el texto esté separado por la misma cantidad o que utilice trpara eliminar el exceso de ellos.

De lo contrario, use herramientas alternativas como awk, sedo ex.

Por ejemplo:

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

Reemplace +q!con -cwqpara guardar los cambios en el lugar.

kenorb
fuente
0

Use un perl one-liner de esta manera:

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

Explicación:

La opción -ehace que el intérprete perl busque la secuencia de comandos en línea, en lugar de en un archivo.

La opción -nhace que la entrada (archivo o STDIN de una tubería) se lea línea por línea.

Opción -l elimina el separador de registro de entrada (dependiente del sistema operativo, nueva línea en UNIX por defecto) después de leer la línea, y lo agrega al final de cadaprint

La opción -ahace que cada línea de entrada se divida en el espacio en blanco en una matriz @F, y $F[-2]es el segundo elemento que cuenta desde el final, que es el campo que desea. También puede usar $F[$#F-1], donde $#Fes el último índice de la matriz @F, que es ligeramente menos legible.

Timur Shtatland
fuente