Ordinamento univoco: reindirizzare l'output sullo stesso file


14

Esiste un modo breve per salvare l'output della pipe nello stesso file che viene elaborato. Ad esempio, questo è quello che sto effettivamente facendo

$ cat filename | sort | uniq > result
$ rm -f filename
$ mv result filename

Mi chiedevo se c'era un modo per farlo in una sola riga (non aggiungere quei comandi usando &&)

Questo non è il modo, ma per avere un'idea

$ cat filename | sort | uniq > filename

2
echo $(cat filename | sort | uniq > result) > filenameo qualcosa ? Solo di passaggio, non ho tempo di provarlo.
MrVaykadji,

Risposte:


18

Puoi usare spongedal pacchetto moreutils :

LC_ALL=C sort -u filename | sponge filename

Inoltre non è necessario pipe per uniq, poiché quando sortha l' -uopzione per le linee uniche durante l'ordinamento.

Si noti che sul sistema GNU con locali UTF-8, sort -uo sort | uniqnon ti ha dato linee uniche, ma il primo dalla sequenza di linee che ordinano lo stesso nella locale corrente.

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=en_US.utf8 sort | LC_ALL=en_US.utf8 uniq

ti ha dato solo . La modifica della locale in C forza l'ordinamento in base ai valori byte:

$ export LC_ALL=C
$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C sort | LC_ALL=C uniq


12

Non è necessario alcun comando aggiuntivo come cate uniqe anche senza utilizzare il rmcomando e il mvcomando per rimuovere e rinominare il nome file. basta usare un semplice comando.

sort -u filename -o filename


 -u, --unique
        with -c, check for strict ordering; without -c, output only  the
        first of an equal run

 -o, --output=FILE
        write result to FILE instead of standard output

Come funziona?

sortcomando ordina il tuo nome file e con l' -uopzione, rimuove le righe duplicate da esso. quindi con l' -oopzione scrive l'output nello stesso file con il metodo sul posto.


3
Se il sistema si arresta in modo anomalo quando sortè in esecuzione, perderai il file originale.
cuonglm,

@Gnouc Quindi, questa è la fine della sfortuna !! : '(
αғsнιη,

1
Grazie! in questo esempio, con "ort "in particolare, dovrei farlo. Tuttavia stavo pensando a un caso generale. @Gnouc, ahah non c'è modo di pensare che se non ti fosse successo, vero?
sbiancato il

3

Il tuo esempio suggerito (sotto) non funziona perché in realtà dovresti leggere e scrivere nello stesso file contemporaneamente.

$ cat filename | sort | uniq > filename

L'idea con una pipe o un reindirizzamento è che il comando sul lato sinistro e destro di ogni pipe o reindirizzamento venga eseguito contemporaneamente, in parallelo. Il comando a destra elabora le informazioni man mano che vengono passate dal comando a sinistra, mentre il comando a sinistra è ancora in esecuzione.

Affinché lo scenario funzioni, il comando che legge dal file dovrebbe terminare prima che inizi il comando che scrive nel file. Affinché ciò funzioni, è necessario reindirizzare prima l'output in una posizione temporanea, quindi una volta terminato, inviarlo dalla posizione temporanea al file.

Un modo migliore per farlo è fondamentalmente come nel tuo esempio precedente, in cui reindirizzi a un file temporaneo, quindi rinominalo nuovamente nell'originale (tranne per il fatto che non è necessario eliminare prima il file, perché lo spostamento elimina qualsiasi destinazione esistente) .

$ cat filename | sort | uniq > result
$ mv -f result filename

Potresti anche salvarlo in una variabile stringa, tranne per il fatto che funziona solo quando i dati sono abbastanza piccoli da contenere tutti in memoria contemporaneamente.


Come qualcuno ha inserito in una modifica suggerita, puoi passare cat filename | sorta solo sort filename- catnon è necessario qui.
thomasrutter,

Il mio esempio di seguito non era il modo di farlo. Grazie per il chiarimento. catpotrebbe non essere necessario in questo caso, ma mi stavo concentrando sulla parte di reindirizzamento.
sbiancato dal

1
Stavo spiegando perché il tuo esempio di seguito non funzionerebbe. So che sapevi che non funzionava.
thomasrutter,

Grazie per il chiarimento! In realtà non sapevo cosa stesse realmente accadendo.
sbiancato dal

2

Puoi usare il teecomando:

sort -u filename | tee filename > /dev/null

Il teecomando legge dallo standard input e scrive nello standard output e nei file.


2
Questo non funziona per me.
pjvandehaar,

3
Questo non funziona askubuntu.com/a/752451
Steven Penny,

Questo fa il lavoro per me. ad esempio, per spostare una riga nella parte inferiore di un file: (cat ~/file | grep -v 3662 ; printentry 3662) | tee ~/file > /dev/nullfunziona. Come nel post originale, questo non funziona se non hai > ~/fileil tee. Tee sembra simile qui sort -o file, che scrive nel file indicato senza continuare la stessa pipe.
Joshua Goldberg,

Aspetta, scusa! Ho visto empiricamente questo perderà imprevedibilmente i dati, come spiegato nel link di @Steven. Crea un file con i numeri 1..9 su 9 righe. Di seguito funzionerà più volte, e quindi occasionalmente rimuoverò tutti i dati dal file: (cat x | grep -v 7 ; echo 7) | tee x > /dev/null; cat x raccomando un file temporaneo e / mvo forse la soluzione dal link di @ Steven.
Joshua Goldberg,

@JoshuaGoldberg hai visto la mia risposta su questa pagina?
Steven Penny,

0

Puoi usare Vim in modalità Ex:

ex -sc 'sort u|x' filename
  1. sort u ordinamento unico

  2. x scrivere se sono state apportate (hanno) delle modifiche ed uscire

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.