Use el espacio como delimitador con el comando de corte

328

Quiero usar el espacio como delimitador con el cutcomando.

¿Qué sintaxis puedo usar para esto?

Jaelebi
fuente
42
falsa, la página del manual de corte no explica esto y es, en general, no es informativo
UncleZeiv
2
Además, el "corte de información" no mejora en este caso.
Cardiff Space Man
3
@ mklement0 si recuerdo, estaba respondiendo a un comentario que desde entonces se ha eliminado, que rechazaba esta pregunta como respondida en la página de manual, que en mi opinión era "falsa", independientemente de que haya una buena razón para ello. o no, ahora, aunque reconozco que podría haber una buena razón para esta falta de información, sigo pensando que la documentación sin ejemplos de uso común a menudo es al menos irritante, cuando no es completamente inútil
UncleZeiv
3
@UncleZeiv Lo tengo; gracias por aclararlo; Dado el interés en esta pregunta, es justo asumir que la manpágina no es suficiente. Echemos un vistazo: " -d delimÚselo delimcomo delimitador de campo en lugar del carácter de tabulación". (BSD cut, pero la versión GNU y la especificación POSIX dicen lo mismo). El uso de un shell para invocar cut- el típico caso - por lo tanto requiere que saber cómo generalmente pasan un espacio como argumento usando la sintaxis del shell , lo que sin duda no es el cuttrabajo de página de manual. Sin embargo, los ejemplos del mundo real siempre ayudan, y la página de manual de GNU carece de ellos.
mklement0
44
aunque la respuesta seleccionada es técnicamente correcta, considere seleccionar la respuesta más reciente y completa de @ mklement0 como la respuesta canónica para que se filtre a la parte superior.
David LeBauer

Respuestas:

367
cut -d ' ' -f 2

Donde 2 es el número de campo del campo delimitado por espacios que desea.

RichieHindle
fuente
2
¿Puedes decirle a cut que use cualquier número de cierto carácter como delimitador, como en RegEx? por ejemplo, cualquier número de espacios, por ejemplo \ s +
anfibio
3
@foampile No, no creo que puedas.
Jonathan Hartley
66
No puede usar expresiones regulares con cut, pero puede con el cutsque intenta "arreglar" todas las cutlimitaciones: github.com/arielf/cuts
arielf
¿Puedes obtener cada tercer campo delimitado por espacios? como cut -d ' ' -f 3,6,9,12,15,18sin tener que especificar cada número?
Monocito
169

Por lo general, si usa el espacio como delimitador, desea tratar varios espacios como uno solo, porque analiza la salida de un comando alineando algunas columnas con espacios. (y la búsqueda de Google para eso me llevó aquí)

En este caso, un solo cutcomando no es suficiente y debe usar:

tr -s ' ' | cut -d ' ' -f 2

O

awk '{print $2}'
BeniBela
fuente
2
Gracias por el ejemplo de uso de awk, justo lo que necesitaba.
spazm
44

Para complementar las respuestas existentes y útiles; punta del sombrero a QZ Support por alentarme a publicar una respuesta por separado:

Aquí entran en juego dos mecanismos distintos :

  • (a) si cut en sí requiere el delimitador (espacio, en este caso) se pasa a la -dopción de ser un argumento separado o si es aceptable para añadirlo directamente a -d.

  • (b) cómo el shell generalmente analiza los argumentos antes de pasarlos al comando que se invoca.

(a) se responde con una cita de las directrices POSIX para servicios públicos (énfasis mío)

Si la SINOPSIS de una utilidad estándar muestra una opción con un argumento de opción obligatorio, una [...] aplicación conforme utilizará argumentos separados para esa opción y su argumento de opción . Sin embargo , una implementación conforme también permitirá que las aplicaciones especifiquen la opción y el argumento de la opción en la misma cadena de argumento sin caracteres intermedios .

En otras palabras: en este caso, como -del argumento de opción es obligatorio , puede elegir si desea especificar el delimitador como :

  • (s) CUALQUIERA: un argumento separado
  • (d) OR: como un valor directamente asociado a-d .

Una vez que haya elegido (s) o (d), lo que importa es el análisis literal de cadena del shell - (b):

  • Con enfoque (s) , todas las siguientes formas son EQUIVALENTES:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • Con el enfoque (d) , todas las siguientes formas son EQUIVALENTES:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

La equivalencia se explica por el procesamiento literal de cadena del shell :

Todas las soluciones anteriores dan como resultado la misma cadena (en cada grupo) cuando las cutve :

  • (s) : cutve -d, como su propio argumento, seguido de un argumento separado que contiene un carácter espacial, ¡sin comillas ni \prefijo!

  • (d) : cutve -d más un carácter espacial, ¡sin comillas ni \prefijo! - Como parte del mismo argumento.

La razón por la cual los formularios en los respectivos grupos son en última instancia idénticos es doble, en función de cómo el shell analiza los literales de cadena :

  • El shell permite que el literal se especifique tal cual es a través de un mecanismo llamado cita , que puede tomar varias formas :
    • cadenas de comillas simples : el contenido dentro '...'se toma literalmente y forma un argumento único
    • cadenas de doble comillas : el contenido dentro "..."también forma un argumento único , pero está sujeto a interpolación (expande referencias variables como $varsustituciones de comandos ( $(...)o `...`) o expansiones aritméticas ( $(( ... ))).
    • \-comillas de caracteres individuales : un carácter \precedente a un solo carácter hace que ese carácter se interprete como un literal.
  • Citando se complementa con eliminación de comillas , lo que significa que una vez que la envoltura ha analizado una línea de comando, que elimina los caracteres cita de los argumentos (que encierran '...'o "..."o \instancias) - por lo tanto, el ser de comandos invoca nunca ve los caracteres de comillas .
mklement0
fuente
36

También puede decir:

cut -d\  -f 2

Tenga en cuenta que hay dos espacios después de la barra invertida.

Chas Owens
fuente
30
La persona que sabe que '\' escapa al siguiente personaje sería muy cuidadoso al notar lo que vino después. Usar '\' para escapar de caracteres espaciales como este es un idioma muy común.
Jonathan Hartley
3
@Jonathan Hartley comúnmente la mayoría de los códigos son ilegibles :) :)
Luca Borrione
1
Desde una perspectiva de Linux / Unix, \ fue mi primer intento y funcionó. Estoy de acuerdo en que es menos obvio en comparación con ' ', pero estoy seguro de que muchos se alegran de leerlo aquí como una garantía de comportamiento. Para una mejor comprensión, consulte el comentario de @ mklement0 a continuación.
tresf
Corrección de @JonathanHartley: "la persona egoísta que sabe que '\' escapa al siguiente personaje y asume que todos los demás también lo saben". Para proyectos personales, esto no se aplica, pero en un entorno de equipo, esa suposición es muy peligrosa (y potencialmente costosa).
Eduard Nicodei
1
@EduardNicodei Oh, estoy de acuerdo. Estábamos hablando de lectores del código ("¿quién se da cuenta ...?"), No de autores. Pero también, en algunos equipos está bien asumir un cierto nivel de competencia. Depende del medio ambiente.
Jonathan Hartley
5

Me acabo de descubrir que también se puede utilizar "-d ":

cut "-d "

Prueba

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am
fedorqui 'así que deja de dañar'
fuente
1
De hecho, o '-d '.
mklement0
3
Tenga en cuenta que a partir cut's perspectiva todos los siguientes son idénticos: "-d ", '-d ', -d" ", -d' ', y -d\<space>: todas las formas directamente Incluya el argumento opción (un espacio) a la opción ( -d) y el resultado en la exacta misma cadena en el momento en cutque ve: una sola argumento que contiene d seguido de un espacio, después de que el shell haya realizado la eliminación de comillas
mklement0
1
La respuesta de @ mklement0 debería ser la respuesta. Es el más completo en esta página (aunque es un comentario).
tresf
@ QZSupport: agradezco el sentimiento y el aliento; me ha inspirado a publicar mi propia respuesta con información de fondo adicional.
mklement0
1
Jajaja fascinante descubrimiento!
Harry
4

No puede hacerlo fácilmente con cortar si los datos tienen, por ejemplo, múltiples espacios. He encontrado útil normalizar la entrada para un procesamiento más fácil. Un truco es usar sed para la normalización como se muestra a continuación.

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar
Anssi
fuente
3

scut , una utilidad de corte (más inteligente pero más lenta que hice) que puede usar cualquier perl regex como un token de última hora. Romper en espacios en blanco es el valor predeterminado, pero también puede romper en expresiones regulares de múltiples caracteres, expresiones regulares alternativas, etc.

scut -f='6 2 8 7' < input.file  > output.file

entonces el comando anterior rompería las columnas en espacios en blanco y extraería los cols (basados ​​en 0) 6 2 8 7 en ese orden.

Harry Mangalam
fuente
0

Tengo una respuesta (admito una respuesta algo confusa) que involucra sedexpresiones regulares y grupos de captura:

  • \S* - primera palabra
  • \s* - delimitador
  • (\S*) - segunda palabra - capturada
  • .* - resto de la línea

Como sedexpresión, el grupo de captura necesita escapar, es decir \(y\) .

El \1devuelve una copia del grupo capturado, es decir, la segunda palabra.

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

Cuando miras esta respuesta, es algo confuso, y, puedes pensar, ¿por qué molestarse? Bueno, espero que algunos digan "¡Ajá!" y usará este patrón para resolver algunos problemas complejos de extracción de texto con una sola sedexpresión.

Stephen Quan
fuente