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