Tengo un archivo en el siguiente formato
Columna1 Columna2 str1 1 str2 2 str3 3
Quiero que las columnas se reorganicen. Intenté debajo del comando
cortar -f2,1 archivo.txt
El comando no reordena las columnas. ¿Alguna idea de por qué no funciona?
Gracias.
cut
que no admita este comando intuitivo de reordenamiento. De todos modos, otro consejo: se puede utilizarawk
's-FS
y-OFS
opciones para el uso de entrada personalizada y separadores de campo de salida (como-d
y--output-delimiter
paracut
).FS
es una opción,OFS
es una variable. egawk -v OFS=";" -F"\t" '{print $2,$1}'
| sed 's/\r//' |
antes deawk
awk '{print $4 "\t" $2 "\t" $6 "\t" $7}' file
También puede combinar
cut
ypaste
:a través de comentarios: es posible evitar bashisms y eliminar una instancia de corte haciendo:
fuente
cut
funciona bien para columnas de longitud variable siempre que tenga un separador de columna único.bash
ismos y eliminar una instancia decut
haciendo:paste file.txt file.txt | cut -f2,3
usando solo el caparazón,
fuente
"$col2"
y"$col1"
, podría haber metacaracteres de shell u otras travesuras en los datos.Puedes usar Perl para eso:
La ventaja de ejecutar perl es que (si conoce a Perl) puede hacer muchos más cálculos en F que reorganizar columnas.
fuente
perl -ae print
funcionacat
para míUtilizando
join
:Notas:
-t $'\t'
En GNUjoin
el más intuitivo-t '\t'
y sin la$
falla, ( coreutils v8.28 y anteriores?); Probablemente sea un error que una solución alternativa$
debería ser necesaria. Ver: unix join separator char .join
necesita dos nombres de archivo, aunque solo se esté trabajando en un archivo. Usar el mismo nombre dos veces engañajoin
para realizar la acción deseada.Para sistemas con bajos recursos
join
ofrece una huella más pequeña que algunas de las herramientas utilizadas en otras respuestas:fuente
Acabo de trabajar en algo muy similar, no soy un experto, pero pensé que compartiría los comandos que he usado. Tenía un csv de varias columnas del que solo necesitaba 4 columnas y luego necesitaba reordenarlas.
Mi archivo era pipe '|' delimitado pero eso se puede cambiar.
¡Es cierto que es realmente duro y listo, pero se puede ajustar para adaptarse!
fuente
Usando sed
Use sed con subexpresiones anidadas de expresiones regulares básicas para capturar y reordenar el contenido de la columna. Este enfoque es más adecuado cuando hay un número limitado de cortes para reordenar columnas, como en este caso.
La idea básica es rodear porciones interesantes del patrón de búsqueda con
\(
y\)
, que se puede reproducir en el patrón de reemplazo con\#
where#
representa la posición secuencial de la subexpresión en el patrón de búsqueda.Por ejemplo:
rendimientos:
El texto fuera de una subexpresión se escanea pero no se retiene para reproducirlo en la cadena de reemplazo.
Aunque la pregunta no discutió columnas de ancho fijo, discutiremos aquí ya que esta es una medida digna de cualquier solución planteada. Para simplificar, supongamos que el archivo está delimitado por espacios, aunque la solución se puede ampliar para otros delimitadores.
Espacios colapsados
Para ilustrar el uso más simple, supongamos que se pueden contraer múltiples espacios en espacios individuales, y los valores de la segunda columna se terminan con EOL (y no con espacio).
Expediente:
Transformar:
Preservar anchos de columna
Extendamos ahora el método a un archivo con columnas de ancho constante, mientras permitimos que las columnas sean de diferentes anchos.
Expediente:
Transformar:
Por último, aunque el ejemplo de la pregunta no tiene cadenas de longitud desigual, esta expresión sed respalda este caso.
Expediente:
Transformar:
Comparación con otros métodos de reordenamiento de columnas bajo shell
Sorprendentemente para una herramienta de manipulación de archivos, awk no es adecuado para cortar desde un campo hasta el final del registro. En sed esto se puede lograr utilizando expresiones regulares, por ejemplo,
\(xxx.*$\)
dóndexxx
está la expresión para que coincida con la columna.Usar pegar y cortar subshells se vuelve complicado cuando se implementan scripts de shell. El código que funciona desde la línea de comandos no se analiza cuando se introduce dentro de un script de shell. Al menos esta fue mi experiencia (lo que me llevó a este enfoque).
fuente
Ampliando la respuesta de @Met, también usando Perl:
Si la entrada y la salida están delimitadas por TAB:
Si la entrada y la salida están delimitadas por espacios en blanco:
Aquí,
-e
le dice a Perl que busque el código en línea, en lugar de en un archivo de script separado,-n
lee la línea de entrada 1 a la vez,-l
elimina el separador de registro de entrada (\n
en * NIX) después de leer la línea (similar achomp
) y agrega salida separador de registros (\n
en * NIX) para cada unoprint
,-a
divide la línea de entrada en el espacio en blanco en la matriz@F
,-F'\t'
en combinación con-a
la línea de entrada en las TAB, en lugar del espacio en blanco en la matriz@F
.@F[1, 0]
es la matriz compuesta de los elementos segundo y primero de la matriz@F
, en este orden. Recuerde que las matrices en Perl están indexadas a cero, mientras que los camposcut
están indexados a 1. Por lo tanto, los campos en@F[0, 1]
son los mismos campos que encut -f1,2
.Tenga en cuenta que dicha notación permite una manipulación más flexible de la entrada que en algunas otras respuestas publicadas anteriormente (que están bien para una tarea simple). Por ejemplo:
fuente