orden inverso de párrafos en el archivo

8

Tengo un archivo que contiene texto en párrafos (líneas con texto separado por una o más líneas vacías). Me gustaría invertir el orden de los párrafos (es decir, el último párrafo se convertirá en el primero, ...), preferiblemente usando sed.

Estoy buscando un comando sed que haría a un archivo de párrafos, lo tacque haría a un archivo de líneas.

Martin Vegter
fuente

Respuestas:

6

El uso sedno es tan recta hacia adelante como se ha mencionado por Joseph R. . Sin embargo, podrías decir:

sed '/./{H;d;};x;s/\n/={NL}=/g' inputfile | \
sed -e 's/^={NL}=//' -e '1!G;h;$!d' | \
sed G | sed 's/={NL}=/\'$'\n/g'

Dada una entrada de muestra:

Para 1 line 1
Para 1 line 2
Para 1 line 3

Para 2 line 1
Para 2 line 2
Para 2 line 3

Para 3 line 1
Para 3 line 2
Para 3 line 3

esto produciría:

Para 3 line 1
Para 3 line 2
Para 3 line 3

Para 2 line 1
Para 2 line 2
Para 2 line 3

Para 1 line 1
Para 1 line 2
Para 1 line 3

Vale la pena mencionar que esta solución (así como la alternativa de Perl) requiere una línea en blanco al final del archivo de entrada para funcionar como se espera.

devnull
fuente
6

Esta solución usa ambos tacy perlpara leer un párrafo a la vez. No requiere leer todo el archivo en la memoria.

tac file | perl -00 -lpe '$_ = join "\n", reverse split /\n/'

Invierta todas las líneas del archivo, luego, para cada párrafo invertido, invierta las líneas.

Glenn Jackman
fuente
Esto se ve muy elegante y eficiente. Sin embargo, esta solución también condensa múltiples líneas vacías (es decir, separando) en una sola
Martin Vegter
3

Puede haber una manera de hacer esto sed, pero dudo que sea simple. Así es como lo haría en Perl:

perl -n00e 'push @paragraphs,$_; END{print for reverse @paragraphs}' your_file

Esto funciona porque definir el separador de registro de entrada como el carácter nulo ( -00) le dice a Perl que opere en modo párrafo. La definición de Perl de un párrafo 1 coincide exactamente con su definición.


1 Mira debajo del encabezadoOther values for $/

Joseph R.
fuente
esto funciona de hecho. El único pequeño problema es que no conserva varias líneas vacías que separan los párrafos. En cambio, todos los párrafos están separados por exactamente una línea vacía.
Martin Vegter
1

Si sus párrafos siempre están separados por una sola línea vacía:

sed '/^$/s/^/\x02/' infile | tr \\n$'\002' $'\003'\\n | \
sed 's/^\x03//;1s/\x03$//;1!G;h;$!d;$a\' | tr $'\003' \\n

Es bastante fácil ver cómo funciona si se rompe en pedazos y ejecutar sed '/^$/s/^/\x02/' infilea continuación, sed '/^$/s/^/\x02/' infile | tr \\n$'\002' $'\003'\\ny así sucesivamente ...


Si sus párrafos están separados por una o más líneas vacías, p. Ej.

Para 1 line 1
Para 1 line 2

Para 2 line 1


Para 3 line 1
Para 3 line 2

Para 4 line 1
Para 4 line 2



Para 5 line 1

y desea revertir el orden de los párrafos pero preservar el orden de "bloques vacíos", puede leer el archivo dos veces:
primero: convierta los párrafos en líneas simples (eliminando los bloques vacíos intermedios) e inviértalos y
segundo: gire los bloques vacíos en líneas individuales, "indexando" el número de líneas vacías en cada bloque (y eliminando las líneas no vacías),
luego pastelos resultados y procesan la salida para restaurar nuevas líneas:

paste -d $'\004' <(sed '/^$/s/^/\x02/' infile | tr \\n$'\002' $'\003'\\n | \
sed -e '/^\x03$/d;s/^\x03//;s/\x03$//;1!G;h;$!d;$a\') \
<(sed -E '/^$/!d;//{:a;N;/^(\n){1,}$/ba;s/\n/\x02/g;s/(.*)\x02.*/\1/}' infile) \
| sed '$!s/\x04/\n/;$s/\x04$//' | tr $'\003\002' \\n\\n

que salidas:

Para 5 line 1

Para 4 line 1
Para 4 line 2


Para 3 line 1
Para 3 line 2

Para 2 line 1



Para 1 line 1
Para 1 line 2

Si no le importa una línea final adicional en la salida, puede soltar la última sed:

paste -d $'\n' <(sed '/^$/s/^/\x02/' infile | tr \\n$'\002' $'\003'\\n | \
sed -e '/^\x03$/d;s/^\x03//;s/\x03$//;1!G;h;$!d;$a\') \
<(sed -E '/^$/!d;//{:a;N;/^(\n){1,}$/ba;s/\n/\x02/g;s/(.*)\x02.*/\1/}' infile) | \
tr $'\003\002' \\n\\n

Estos suponen que la primera y la última línea no están vacías (y no \x02, \x03o \x04en la entrada).

revs don_crissti
fuente
1

PUEDES hacerlo con una sola instancia de sed; No se necesitan tuberías. Dado que sedsolo hace una pasada a través del documento y dado que la parte del archivo requerida como el comienzo de la salida está al final del archivo, requerirá mantener todo el archivo en la memoria interior sed(en el espacio de retención), por lo que puede No escala bien. Pero responde la pregunta exactamente:

:getpara
   ${
      s/$/\
/
      G
      s/\n\n$//
      q
   }
   N
   /\n$/!bgetpara
G
h
$!d
s/\n\n$//
q

Si no hay una nueva línea final, esto todavía funciona bien. Si hay una nueva línea final, se suprime en la salida (es decir, no habrá una nueva línea inicial en la salida). Si hay (por ejemplo) 5 líneas nuevas en la entrada, habrá 4 líneas nuevas en la salida.

Se conservan los espacios entre párrafos.

El espacio en blanco en una línea vacía de otra manera NO se trata como un salto de párrafo, pero esa es una característica, no un error. :)

También puede hacer esto como una línea mucho menos legible:

sed ':k;${;s/\(\(\n\).*\)$/\1\2/;G;s/\n\n$//;q;};N;/\n$/!bk;G;h;$!d;s/\n\n$//;q' inputfile

Aunque esto solo funciona con GNU sed. (Tenga en cuenta el uso complicado de las referencias inversas para realizar s/$/\n/. Sin esto, no sería una línea literal, ya que contendría una barra diagonal inversa-nueva línea).

Comodín
fuente
así que sorbe el archivo, ¿verdad? parece que pones todo en el espacio de espera. w / G;h. Puede mencionar algo sobre restricciones de entrada o similar.
mikeserv
No probé el one-liner porque estoy trabajando desde mi Mac y no tengo GNU a sedmano, pero la versión del script definitivamente conserva las brechas entre los párrafos. Acabo de probarlo en tu entrada. ¿Probaste la versión del script?
Comodín
@mikeserv: Definitivamente cierto. (Se actualizará esta noche.)
Comodín el
0
gem install facets

ruby -r facets/string \
     -e 'puts $stdin.read.strip.shatter(/\n\n+/).reverse.join("")' < file

Esto debería preservar el espacio entre párrafos (a la vez que es más legible que sed:)) Sin embargo, los accesorios para devnull para una respuesta increíble.

Amadan
fuente