ordine inverso dei paragrafi nel file


8

Ho un file contenente testo nei paragrafi (righe con testo separati da una o più righe vuote). Vorrei invertire l'ordine dei paragrafi (ovvero l'ultimo paragrafo diventerà il primo, ...), preferibilmente usando sed.

Sto cercando un comando sed che farebbe un file di paragrafi, cosa tacfarebbe un file di righe.

Risposte:


6

L'uso sednon è così semplice come indicato da Joseph R .. Tuttavia, potresti dire:

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'

Dato un input di esempio:

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

questo produrrebbe:

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 ricordare che questa soluzione (così come quella Perl alternativa) richiede una riga vuota alla fine del file di input per funzionare come previsto.


6

Questa soluzione utilizza entrambi tace perlper leggere un paragrafo alla volta. Non richiede la lettura dell'intero file in memoria.

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

Invertire tutte le righe del file, quindi per ogni paragrafo invertito, invertire le righe.


Sembra molto elegante ed efficiente. Tuttavia, questa soluzione condensa anche più righe vuote (cioè separando) in una sola
Martin Vegter,

3

Potrebbe esserci un modo per farlo sed, ma dubito che sarà semplice. Ecco come lo farei in Perl:

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

Questo funziona perché la definizione del separatore del record di input come carattere null ( -00) dice a Perl di operare in modalità paragrafo. La definizione di Perl di un paragrafo 1 corrisponde esattamente alla tua definizione.


1 Guarda sotto l'intestazioneOther values for $/


funziona davvero. L'unico piccolo problema è che non conserva più righe vuote che separano i paragrafi. Invece, tutti i paragrafi sono separati da esattamente una riga vuota.
Martin Vegter,

1

Se i tuoi paragrafi sono sempre separati da un'unica riga vuota:

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

È abbastanza facile vedere come funziona se lo spezzi in pezzi e corri sed '/^$/s/^/\x02/' infileallora sed '/^$/s/^/\x02/' infile | tr \\n$'\002' $'\003'\\ne così via ...


Se i tuoi paragrafi sono separati da una o più righe vuote, ad es

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

e vuoi invertire l'ordine dei paragrafi ma preservare l'ordine dei "blocchi vuoti" potresti leggere il file due volte:
1 °: trasforma i paragrafi in righe singole (rimuovendo i blocchi vuoti in mezzo) e invertili e
2 °: trasforma i blocchi vuoti in singole righe, "indicizzando" il numero di righe vuote in ciascun blocco (e rimuovendo le righe non vuote),
quindi pastei risultati ed elaborare l'output per ripristinare le nuove righe:

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

che produce:

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

Se non ti dispiace una riga finale in più nell'output potresti eliminare l'ultima 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

Questi presuppongono che la prima e l'ultima riga non siano vuote (e no \x02, \x03o \x04nell'input).


1

Puoi farlo con una singola istanza di sed; nessuna tubatura necessaria. Poiché sedeffettua solo un passaggio attraverso il documento e poiché la parte del file richiesta come inizio dell'output si trova alla fine del file, richiederà di conservare l'intero file in memoria all'interno sed(nello spazio di attesa), quindi potrebbe non ridimensionare bene. Ma risponde esattamente alla domanda:

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

Se non ci sono newline finali, questo funziona ancora bene. Se esiste una nuova riga finale, questa viene soppressa nell'output (ovvero non ci sarà una nuova riga iniziale nell'output). Se ci sono (ad esempio) 5 newline finali nell'input, ci saranno 4 newline principali nell'output.

Gli spazi tra i paragrafi vengono conservati.

Lo spazio bianco su una riga altrimenti vuota NON viene trattato come un'interruzione di paragrafo, ma questa è una caratteristica, non un bug. :)

Puoi anche farlo come il one-liner molto meno leggibile:

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

Anche se questo funziona solo con GNU sed. (Nota l'uso complicato di backreferences da eseguire s/$/\n/. Senza questo non sarebbe un letterale one-liner in quanto conterrebbe una barra rovesciata-newline.)


quindi hai bevuto il file, giusto? sembra che tu abbia messo tutto nello spazio di attesa. w / G;h. potresti menzionare qualcosa sulle restrizioni di input o simili.
Mikeserv,

Non ho testato il one-liner perché sto lavorando dal mio Mac e non ho GNU a sedportata di mano, ma la versione dello script conserva sicuramente le lacune tra i paragrafi. Ho appena testato il tuo contributo. Hai provato la versione dello script?
Carattere jolly

@mikeserv: Sicuramente vero. (Si aggiornerà stasera.)
Wildcard

0
gem install facets

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

Questo dovrebbe preservare la spaziatura del paragrafo (pur essendo più leggibile di sed:)) Anche se, puntelli a devnull per una risposta fantastica.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.