Estoy tratando de cambiar el orden de las líneas en un patrón específico. Trabajando con un archivo con muchas líneas (ej. 99 líneas). Por cada tres líneas, me gustaría que la segunda línea sea la tercera línea, y que la tercera sea la segunda línea.
EJEMPLO.
1- entrada:
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.
...
2- Salida:
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
...
linux
text-processing
command-line
Annick Raymond
fuente
fuente
NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
.Es decir,
p
borre la línea actual, obtenga lan
extensión anterior, lah
antigua, obtenga la línean
externaG
y la línea retenida (añádala al espacio del patrón) yp
borre el espacio del patrón de 2 líneas con las líneas tercera y segunda intercambiadas.fuente
Otro enfoque awk :
La salida:
(getline L2)>0 && (getline L3)>0
- extrae los siguientes 2 registros si existencada segundo y tercer registro se asignan a variables
L2
yL3
respectivamentefuente
line2
, etc.Usando
perl
y un guión corto:El script procesa todo el archivo, para cada línea (almacenada
$_
) obtendrá las siguientes dos líneas ($l2
y$l3
) y las imprimirá en el orden solicitado: línea1, línea3, línea2.fuente
Una forma podría ser la siguiente:
Alternativamente,
Resultados
fuente
¿Por qué no simplemente hacer un ciclo while? En forma expandida:
En "formato de línea única":
Salidas:
fuente
Perl
La idea aquí es que usamos un operador de módulo
%
con una$.
variable de número de línea , para determinar cuál es cada primero, cuál es cada segundo y cuál es cada tercera línea. Para cada tercera línea, el resto es 0, mientras que para cada primera y segunda línea tendrá los números correspondientes.Prueba:
Mejora menor
El enfoque con el almacenamiento de la segunda línea en una variable tiene un defecto. ¿Qué sucede si la última línea es la "segunda", es decir, para ese número de línea el resto es 2? El código original en mi y la respuesta de DopeGhoti no se imprimirá
My dog is orange
si omitimos la última línea. La solución para eso en ambos casos es usar elEND{}
bloque de código, desarmando la variable temporal después de imprimir. En otras palabras:y
De esta manera, el código funcionará para un número arbitrario de líneas en un archivo, no solo aquellas divisibles por 3.
Solución adicional para el problema mencionado en los comentarios
En el caso de awk, si la última línea del archivo produce una salida de 1 por $. % 3, el código anterior tiene problemas para generar una nueva línea en blanco debido a la impresión incondicional de
END{print delay}
, ya que laprint
función mencionada en los comentarios siempre agrega nueva línea a cualquier variable en la que esté operando. En el caso de laperl
versión, este problema no ocurre, ya que con la función-ne
flagsprint
no se agrega la nueva línea.Sin embargo, la solución en el caso de awk es hacer condicional, como lo menciona Dope Ghoti en los comentarios, es verificar la longitud de la variable temporal. La versión perl de la misma solución sería:
fuente
awk
)NR%3 == 0 { print; print delay; delay=""} END { if(length(delay) != 0 ) { print delay }
.-ne
banderas no genera una nueva línea. De hecho, se imprime, pero es una cadena nula, sin línea nueva. No obstante, he agregado la mención del problema y la misma solución en mi respuesta. Gracias !Empuje
No es adecuado para archivos largos, pero sigue siendo útil si solo estaba editando un archivo y desea, por ejemplo, reordenar algunas estrofas yaml.
Primero grabe una macro:
Y luego repita el número deseado de veces:
O solo por ejemplo
Explicación:
fuente
@q @q @q
, es posible hacerlo de esta manera3@q
: repita tres veces.100@q
- Repita la macro 100 veces.Uso:
./shuffle_lines.awk input.txt
Verifique shebang
#!/usr/bin/awk -f
, porque laawk
ubicación puede diferir en su sistema.fuente