È necessario spostare l'ultima riga del file nella seconda riga dello stesso file


8

Ho un file 'test' in linux con i seguenti dati.

aaaaaa
bbbbbb
cccccc
dddddd
eeeeee

Ho bisogno di tagliare l'ultima riga di questo file e metterlo in seconda posizione. Deve apparire come sotto.

aaaaaa
eeeeee
bbbbbb
cccccc
dddddd

Risposte:


9

Questo problema potrebbe effettivamente essere più semplice da gestire ed, dal momento che è fondamentalmente un editor di testo utilizzabile tramite script, piuttosto che un processore di flusso. Utilizzando ed, non è necessario salvare tutte le righe del file in un array, ad esempio, poiché lo sta già facendo per te.

# Create test file
~> printf "%s\n" aaaaaa bbbbbb cccccc dddddd eeeeee >test.txt
~> cat test.txt
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee

# Use ed to open the file, move the last line after the first, save, and quit
~> printf "%s\n" '$m1' wq | ed test.txt
35
35
~> cat test.txt
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd

5

Hold buffer mode:

sed '$x;1!H;1p;$!d;x;s/\n//
' <<\IN
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
IN

... che Hinvecchierà ogni riga che !non è la prima, e la prima che pstrappa. Nella $ultima riga It E xmodifiche tengono struttura modello prima fa il Hvecchio - che ottiene i righe salvate allegate all'ultima linea - poi deletes dall'uscita tutte le linee che sono !non l' $ultimo.

Sulla $ultima linea ë xancora modifiche spazi, s///ubstitutes via il primo \ncarattere ewline - che si prende cura di extra aggiunto sulla linea 2 - quindi autoprints del lotto.

PRODUZIONE:

aaaaaa
eeeeee
bbbbbb
cccccc
dddddd

senza usare il buffer di attesa:

cat <<\IN >infile
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
IN

... solo per salvare il tuo esempio in un file reale ...

sed '1p;$!d;r infile' <infile | sed '3d;$d'

Che reindirizza <infileai primi seds' stdin, che solo prints la prima linea prima dEliminazione dall'uscita tutte le linee che sono !non l' $ultima. L'ultima riga è autoprinted, ma è anche l'unica linea su cui viene eseguito il comando finale - vale a read l'intero infile nuovamente a stdout. Tutto ciò viene passato attraverso il |tubo al secondo sedche poi deve solo deliminare dalla sua uscita la sua terza e ultima linea di ingresso per completare la riorganizzazione.

PRODUZIONE:

aaaaaa
eeeeee
bbbbbb
cccccc
dddddd

bello, +1. Non ricordo di aver mai pubblicato awksoluzioni, sei un grande sedfan o forse hai scritto sed? ;-)
iruvar,

@ 1_CR - non so come usare awk- non ho mai provato. forse un giorno ...
Mikeserv,

2

Un approccio ingenuo usando awk:

~$ awk '{a[NR]=$0}END{print a[1];print a[NR];for(i=2;i<NR;i++){print a[i]}}' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd

Memorizzi ogni riga anell'array, quindi stampi l'array nell'ordine desiderato (1a riga, ultima ( NR) e da 2 a penultima.

Usando una combinazione di testa / coda e sed:

~$ head -1 f;tail -1 f;sed '1d;$d' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd

Stampa la prima riga, l'ultima e con sed elimina la prima e l'ultima.


Solo con sed, sono stato in grado di trovare solo questo comando. Sono sicuro che ci sono modi migliori:

~$ sed '${p;x;s/^\n//;p};2,${H;d}' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd

Se è la prima riga, stampala (impostazione predefinita).
Dalla seconda riga, inseriscilo nel buffer di mantenimento ( H), ed eliminalo dallo spazio modello ( d). E se è l'ultima riga, stampala ( p), quindi ottieni il buffer di conservazione ( x), elimina la riga vuota ( s/^\n//) e stampala ( p).


Il mio primo istinto sarebbe quello di usare il metodo testa / coda. Un'alternativa alla sedparte sarebbe qualcosa di simile head -n -1 f | tail -n +2.
Sparhawk,

@Sparhawk la -1sintassi per headnon è portatile.
Mikeserv,

1

Con perl:

perl -e 'my @lines = <>; print for @lines[0, $#lines, 1..$#lines-1]' file

Con awk:

$ awk '
    {lines[NR]=$0}
    END{
        print lines[1], lines[NR];
        for (i=2; i<NR; i++) {print lines[i]}
    }
' OFS=$'\n' file

PRODUZIONE

aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
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.