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.