varios todos renombrar pegar otro mover los directorio desde copiar como carpeta archivos archivo bash unix delimiter cut

bash - todos - mover varios archivos en linux



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

Estoy tratando de extraer un cierto campo (el cuarto) de la secuencia de texto ajustada basada en la columna y espacio. Estoy tratando de usar el comando de cut de la siguiente manera:

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

Desafortunadamente, el cut no trata varios espacios como un delimitador. Pude haber pasado por awk

awk ''{ printf $4; }''

o sed

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

¿Para colapsar los espacios, pero me gustaría saber si hay alguna forma de lidiar con el cut y varios delimitadores de forma nativa?


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

Después de frustrarme con las demasiadas limitaciones del cut , escribí mi propio reemplazo, al que llamé "cortes con esteroides".

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

Un ejemplo, de 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

cuts soportes:

  • detección automática de la mayoría de los delimitadores de campo comunes en los archivos (+ capacidad para anular los valores predeterminados)
  • Delimitadores emparejados multi-char, mixed-char y regex
  • extracción de columnas de múltiples archivos con delimitadores mixtos
  • compensaciones desde el final de la línea (usando números negativos) además del inicio de la línea
  • Pegado de columnas lado a lado automático (no es necesario invocar paste separado)
  • soporte para reordenamiento de campo
  • 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 cut estándar.

Consulte también: https://.com/a/24543231/1296044

Fuente y documentación (software libre): cuts


Como comentó en su pregunta, awk es realmente el camino a seguir. Usar cut es posible junto con tr -s para comprimir espacios, como muestra la respuesta de kev .

Sin embargo, permítanme pasar por todas las combinaciones posibles para futuros lectores. Las explicaciones están en la sección de Prueba.

tr | cortar

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

awk

awk ''{print $4}'' file

golpetazo

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

sed

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

Pruebas

Dado este archivo, vamos a probar 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

golpetazo

Esto lee los campos secuencialmente. Al usar _ , indicamos que esta es una variable desechable como una "variable basura" para ignorar estos campos. De esta manera, almacenamos $myfield como el cuarto campo en el 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 atrapa tres grupos de espacios y ningún espacio con ([^ ]*[ ]*){3} . Luego, captura lo que viene hasta que se imprime con /1 un espacio como el cuarto campo.

$ sed -r ''s/^([^ ]*[ ]*){3}([^ ]*).*//2/'' a 1 2 3 4


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


Este one-liner de Perl muestra qué tan cerca está relacionado Perl con awk:

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

Sin embargo, la matriz @F autosplit comienza en el índice $F[0] mientras que los campos awk comienzan con $1


Tratar:

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

Desde la página de manual de tr :

-s, --squeeze-repeats replace each input sequence of a repeated character that is listed in SET1 with a single occurrence of that character