Tengo un archivo y su contenido se ve así:
a1
b1
c1
aa
bb
cc
aaa
bbb
ccc
d1
e1
f1
dd
ee
ff
ddd
eee
fff
g1
h1
i1
gg
hh
ii
ggg
hhh
iii
¿Cuál es la mejor manera de fusionar las filas con un intervalo fijo (3 en este caso) y obtener algo como:
a1 aa aaa
b1 bb bbb
c1 cc ccc
d1 dd ddd
e1 ee eee
f1 ff fff
g1 gg ggg
h1 hh hhh
i1 ii iii
El algoritmo para obtener la salida de la entrada es:
- Primero obtenemos la fila 1 que es a1.
- sabemos que el intervalo es 3
- Entonces la fila 1, fila (1+3), fila (1+3+3) deben estar en la misma fila
- Del mismo modo, las filas 2, 5, 8 deben estar en la misma fila, etc.
Aquellosa1,Automóvil club británicoyaaaetc. son solo texto ficticio aleatorio y podrían ser cualquier cadena aleatoria. La cuestión es que existe un intervalo fijo entrea1,Automóvil club británicoyaaa.
Actualmente uso la macro de teclado de emacs para realizar esta tarea. Sin embargo, quiero saber si hay mejores maneras de resolver este problema. Gracias de antemano.
Respuesta1
Si estás en gnu
/anything y el número de líneas es múltiplo de 9, puedes ejecutar
split -l9 --filter='pr -3 -s" " -t' infile
Esto divide la entrada en partes de nueve líneas y cada parte se canaliza a pr -3 -s" " -t'
una columna que la divide... Dependiendo del no. de líneas y su longitud es posible que necesites jugar con pr
opciones -w
y -l
. Vea la man
página para más detalles.
Respuesta2
Aquí hay una solución simplista en awk, codificada para obtener tres conjuntos en intervalos de tres líneas:
{
if (NR > 1 && (NR % 9) == 0) {
print a "\n" b "\n" c " " $0
a=""
b=""
c=""
} else if (NR % 3 == 1) {
if (NR % 9 > 1) {
a=a" "$0
} else {
a=$0
}
} else if (NR % 3 == 2) {
if (NR % 9 > 2) {
b=b" "$0
} else {
b=$0
}
} else {
if (NR % 9 > 3) {
c=c" "$0
} else {
c=$0
}
}
}
Guárdelo en un archivo y ejecútelo awk -f thatfile < input
. Estoy seguro de que hay formas más inteligentes de hacerlo, pero no trabajo todos los días.
Respuesta3
Es un poco complicado. No conozco una sola utilidad que pueda hacerlo:
Esta canalización (esencialmente) lee 9 líneas a la vez y se utiliza pr
para formatear en 3 columnas:
# there are 9 single hyphens below
paste -d: -- - - - - - - - - - < file | while read line; do
tr : '\n' <<<"$line" | pr -s" " -T -3
done
a1 aa aaa
b1 bb bbb
c1 cc ccc
d1 dd ddd
e1 ee eee
f1 ff fff
g1 gg ggg
h1 hh hhh
i1 ii iii
Esto supone que no tienes dos puntos en tu texto real.
Respuesta4
Una forma muy sencilla y clara deTXR:
@(repeat)
@x0
@x1
@x2
@y0
@y1
@y2
@z0
@z1
@z2
@ (output)
@x0 @y0 @z0
@x1 @y1 @z1
@x2 @y2 @z2
@ (end)
@(end)
Correr:
$ txr reshape.txr data
a1 aa aaa
b1 bb bbb
c1 cc ccc
d1 dd ddd
e1 ee eee
f1 ff fff
g1 gg ggg
h1 hh hhh
i1 ii iii
Hay formas de condensar esto, pero hay que trabajar un poco más para entenderlas, como por ejemplo:
@(repeat)
@ (collect :times 9)
@line
@ (end)
@ (bind (x y z) @(tuples 3 line))
@ (output)
@ (repeat)
@x @y @z
@ (end)
@ (end)
@(end)
Además, aquí se explica cómo podría implementar alguien que sepa un poco lo que está haciendo en Awk:
{ a[(NR-1)%9] = $0 }
!(NR%9) { print a[0], a[3], a[6]
print a[1], a[4], a[7]
print a[2], a[5], a[8] }
Producción:
$ awk -f reshape.awk data
a1 aa aaa
[ ... ]
i1 ii iii
Y si ese codificador encuentra print
repugnantes los patrones repetidos:
{ a[(NR-1)%9] = $0 }
!(NR%9) { for (i = 0; i < 3; i++)
print a[i], a[i+3], a[i+6] }
Solución TXR Lisp:
[(opip (tuples 3) (tuples 3) (mappend transpose)
(mapcar (aret `@1 @2 @3`)) tprint)
(get-lines)]
Correr:
$ txr reshape.tl < data
En la línea de comando: use -t
, suelte tprint
:
$ txr -t '[(opip (tuples 3) (tuples 3) (mappend transpose)
(mapcar (aret `@1 @2 @3`)))
(get-lines)]' < data
Esto funciona pasando la entrada a través de una tubería que la apuntala en tripletes, luego tripletes de esos tripletes (básicamente matrices de 3x3 hechas de listas anidadas). Estas matrices se transponen individualmente y luego sus filas se unen para formar una lista gigante de tripletes. Estos tripletes se convierten en cadenas con el aret
operador de aplicación parcial una interpolación de cadenas y una salida tprint
que trata las listas de cadenas como líneas para generar. la sintaxis
(aret `@1 @2 @3`)
se expande en algo parecido
(lambda (. args)
(apply (lambda (arg1 arg2 arg3)
`@arg1 @arg2 @arg3`)
args))
Básicamente , crea implícitamente una función anónima de un argumento que trata su argumento como una lista de argumentos para aplicar a una función anónima de 3 argumentos donde @1
y denotan los argumentos. El cuerpo de la función se deriva de la expresión de cuasicadena original sustituyendo estos parámetros numéricos especiales por nombres de argumentos generados por máquina.@2
@3