¿Cómo hacer que el comando 'cortar' trate los mismos delimitadores secuenciales como uno solo?

Resuelto mbaitoff asked hace 13 años • 6 respuestas

Estoy intentando extraer un determinado campo (el cuarto) del flujo de texto ajustado por "espacio" basado en columnas. Estoy intentando usar el cutcomando de la siguiente manera:

cat text.txt | cut -d " " -f 4

Lamentablemente, cutno trata varios espacios como un delimitador. Podría haber hablado a través de awk.

awk '{ printf $4; }'

o sentado

sed -E "s/[[:space:]]+/ /g"

para colapsar los espacios, pero me gustaría saber si hay alguna forma de lidiar con cutvarios delimitadores de forma nativa.

mbaitoff avatar Nov 10 '10 17:11 mbaitoff
Aceptado

Intentar:

tr -s ' ' <text.txt | cut -d ' ' -f4

Desde la trpágina de manual:

-s, --squeeze-repeats reemplaza cada secuencia de entrada de un carácter repetido
                        que aparece en SET1 con una sola aparición
                        de ese personaje
kev avatar Dec 19 '2010 16:12 kev

Como comentas en tu pregunta, awkes realmente el camino a seguir. Es posible usarlo cutjunto con tr -sapretar espacios, como muestra la respuesta de Kev .

Sin embargo, permítanme repasar todas las combinaciones posibles para futuros lectores. Las explicaciones se encuentran en la sección Prueba.

tr| cortar

tr -s ' ' < file | cut -d' ' -f4

awk

awk '{print $4}' file

intento

while read -r _ _ _ myfield _
do
   echo "forth field: $myfield"
done < file

sed

sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' file

Pruebas

Dado este archivo, probemos los comandos:

$ cat a
this   is    line     1 more text
this      is line    2     more text
this    is line 3     more text
this is   line 4            more    text

tr| cortar

$ cut -d' ' -f4 a
is
                        # it does not show what we want!


$ tr -s ' ' < a | cut -d' ' -f4
1
2                       # this makes it!
3
4
$

awk

$ awk '{print $4}' a
1
2
3
4

intento

Esto lee los campos secuencialmente. Al usar _indicamos que esta es una variable desechable como "variable basura" para ignorar estos campos. De esta manera, lo almacenamos $myfieldcomo el cuarto campo del archivo, sin importar los espacios entre ellos.

$ while read -r _ _ _ a _; do echo "4th field: $a"; done < a
4th field: 1
4th field: 2
4th field: 3
4th field: 4

sed

Esto captura tres grupos de espacios y ningún espacio con ([^ ]*[ ]*){3}. Luego, captura todo lo que viene hasta un espacio como el cuarto campo, con el que finalmente se imprime \1.

$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4
fedorqui avatar Sep 23 '2014 10:09 fedorqui

solución más corta/más amigable

Después de sentirme frustrado por las demasiadas limitaciones de cut, escribí mi propio reemplazo, al que pedí cuts"reducir los esteroides".

cuts proporciona lo que probablemente sea la solución más minimalista para este y muchos otros problemas relacionados de cortar/pegar.

Un ejemplo, entre muchos, que aborda esta pregunta en particular:

$ cat text.txt
0   1        2 3
0 1          2   3 4

$ cuts 2 text.txt
2
2

cutsapoya:

  • detección automática de los delimitadores de campos más comunes en archivos (+ capacidad de anular los valores predeterminados)
  • delimitadores coincidentes de múltiples caracteres, caracteres mixtos y expresiones regulares
  • extraer columnas de múltiples archivos con delimitadores mixtos
  • desplazamientos desde el final de la línea (usando números negativos) además del inicio de la línea
  • Pegado automático de columnas una al lado de la otra (no es necesario invocarlas pastepor separado)
  • soporte para reordenamiento de campos
  • un archivo de configuración donde los usuarios pueden cambiar sus preferencias personales
  • gran énfasis en la facilidad de uso y la escritura minimalista requerida

y mucho más. Ninguno de los cuales es proporcionado por estándar cut.

Ver también: https://stackoverflow.com/a/24543231/1296044

Fuente y documentación (software libre): http://arielf.github.io/cuts/

arielf avatar Jul 03 '2014 01:07 arielf

Esta frase breve de Perl muestra cuán estrechamente relacionado está Perl con awk:

perl -lane 'print $F[3]' text.txt

Sin embargo, la @Fmatriz de división automática comienza en el índice $F[0], mientras que los campos awk comienzan con$1

Chris Koknat avatar Sep 09 '2015 17:09 Chris Koknat

Con versiones de cutque conozco no, esto no es posible. cutEs principalmente útil para analizar archivos donde el separador no es un espacio en blanco (por ejemplo /etc/passwd) y que tienen un número fijo de campos. Dos separadores seguidos significan un campo vacío, y eso también se aplica a los espacios en blanco.

Benoit avatar Nov 10 '2010 10:11 Benoit