
Tengo un archivo que se parece a continuación:
1
4 5 6 7 19
20
22
24 26 27
29
30
31
32
34
40
50
56
58
100
234 235 270 500
1234 1235 1236 1237
2300
2303
2304
2307
2309
Como queda claro, hay algunas filas con más de 1 columna y otras con una sola columna. Me gustaría unir filas de una sola columna de modo que haya como máximo 4 columnas en cada fila combinada. Entonces la salida debería verse así:
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309
¿Alguna sugerencia sobre cómo hacer esto, considerando que los datos reales son grandes?
Respuesta1
Un poco idiomático pero trabajando con gnu awk:
awk '{printf "%s",(NF==1?$0 FS:(c==0?"":RS) $0 RS)} \
{(NF==1?++c:c=0)} \
c==4{printf "\n";c=0} \
END{printf "\n"}' file
#Output
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309
Explicación:
variables awk:
NF=Número de campos
FS=Separador de campos = espacio por defecto
RS=Separador de registros= nueva línea por defecto.
c=contador
Línea 1: {printf "%s",(NF==1?$0 FS:(c==0?"":RS) $0 RS)}
: ternario anidado si operaciones
#Single ternary if operation:
condition?true action:false action
#Nested if operations:
condition1?true action 1:(condition2:true action2:false action2) #nested ternary if operations
-------------------------[ ^ false action1 ^ ]
Esto se puede explicar en pseudocódigo como:
if NF==1 then print $0 and print FS
else (if c==0 then print "" else print RS) and print $0 and print RS again
Línea 2: {(NF==1?++c:c=0)}
: Otra operación if ternaria que se puede expresar como:
If NF==1 (line has one field)
then increase counter c by one
else reset counter c.
Línea 3 : c==4{printf "\n";c=0}
Sintaxis clásica de awk:condition{action}
If counter c==4 then print a new line and reset counter c
Línea 4: END{printf "\n"}' file
: Esto simplemente imprime una nueva línea al final del script.
Respuesta2
Puedes utilizar sed
para obtener lo que deseas:
sed -e '
/./!b
/[^[:space:]]/!b
/[^[:space:]][[:blank:]]\{1,\}[^[:space:]]/b
:loop
$q;N
/\n.*\S[[:blank:]]\+\S/b
s/\n/ /;tdummy
:dummy
s/[[:space:]]\{1,\}/&/3;t
bloop
' yourfile
Explicaciones
- Omita líneas vacías, en blanco y con NF > 1.
- Configure un bucle do- while en el punto donde el espacio del patrón contiene una línea de campo único.
- Tomamos la siguiente línea y verificamos si tiene NF > 1, momento en el cual imprimimos todo el espacio del patrón y volvemos a leer la siguiente línea.
- Ahora sabemos que la siguiente línea también es de un solo campo, así que continuamos y recortamos la nueva línea que une estas dos partes en el espacio del patrón.
- ¿El espacio del patrón ya tiene 3 espacios? En caso afirmativo, imprimimos todo el espacio del patrón y comenzamos a leer la siguiente línea.
- De lo contrario, volvemos al bucle que a su vez leerá la siguiente línea pero la adjuntará al espacio del patrón existente.
Resultado
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309
Respuesta3
Uso: ./join_rows.awk input.txt
Verifique Shebang #!/usr/bin/awk -f
, porque la awk
ubicación puede diferir en su sistema.
#!/usr/bin/awk -f
BEGIN {
count = 1;
}
{
if (NF == 1) {
if (count > 1 && count <= 4) printf " ";
printf "%s", $1;
count++;
if (count > 4) {
printf "\n";
count = 1;
}
} else {
if (count > 1) printf "\n";
print;
count = 1;
}
}
END {
if(count > 1) printf "\n";
}
Producción:
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309
Respuesta4
Extendidopapar moscasacercarse:
reorganizar_columnas.awkguion:
#!/bin/awk -f
function printRow(a, i, v)
{
for (i in a) {
printf "%s ", a[i]
}
print ""
delete a
}
NF <= 2{
for (i=1; i<=NF; i++) {
a[++c] = $i
if (length(a) == 4) {
c = 0
printRow(a)
}
}
}
NF > 2{
if (length(a) > 0) {
c = 0
printRow(a)
}
print $0
}
END{ print }
Uso:
awk -f rearrange_columns.awk yourfile
La salida:
1
4 5 6 7 19
20 22
24 26 27
29 30 31 32
34 40 50 56
58 100
234 235 270 500
1234 1235 1236 1237
2300 2303 2304 2307
2309