accoda il testo con l'eco senza una nuova riga


15

Voglio aggiungere testo a file come echo "abc" >>file.txt.

Ma questo si aggiunge abcdopo una nuova riga

Come posso aggiungere abcalla fine del file con echo senza una nuova riga?


2
Il file ha già una nuova riga, che stai solo aggiungendo dopo di esso. Quindi dovrai sostituire il carattere di nuova riga dall'ultima riga, con "abc".
ctrl-alt-delor,

Benvenuto in StackExchange! La tua domanda è buona; sarebbe stato meglio se avessi specificato esempi del contenuto del tuo file (prima dell'aggiunta, cosa ottieni dopo l'aggiunta, cosa volevi invece). Lo dico perché una delle risposte è come aggiungere abcsenza una nuova riga finale, che (dopo aver letto attentamente la tua domanda) non sembra essere ciò che desideri.
Legge

Risposte:


19

echo "abc" >>file.txtmette una nuova riga dopo abc , non prima. Se si finisce con abcsulla propria linea, ciò significa che la nuova riga precedente abcera già presente in file.txt.

Si noti che è perfettamente normale che un file di testo termini in una nuova riga. Su unix, una riga è costituita da una sequenza di caratteri diversa da null⁰ o newline seguita da una nuova riga. 1 Pertanto qualsiasi file di testo non vuoto termina con un carattere di nuova riga.

Se vuoi aggiungere del testo all'ultima riga di un file, non puoi farlo con >>, perché questo accoda sempre al file, quindi scrive sempre dopo l'ultima riga. È invece necessario uno strumento in grado di modificare un file esistente. Ad esempio, puoi usare sed :

sed '$ s/$/abc/' file.txt >file.txt.new && mv file.txt.new file.txt

Nel comando sed, il primo $significa " s/REGEX/REPLACEMENT/esegui il comando seguente solo sull'ultima riga", il comando sostituisce REGEX con REPLACEMENT e l'espressione regolare $corrisponde alla fine della riga.

Il comando sed di Linux ha una funzione integrata per automatizzare questa sequenza di creazione di un nuovo file e sostituire, in modo da poter abbreviare

sed -i '$ s/$/abc/' file.txt

Questo è un byte nullo, che ASCII chiama NUL e Unicode chiama U + 0000. I programmi di elaborazione del testo possono o meno affrontare questo personaggio.
1 Vedere le definizioni di file di testo , linea e carattere di nuova riga nella sezione "Definizioni" del capitolo Definizioni di base di IEEE 1003.1-2008: 2016.


2
Il tuo secondo paragrafo intende implicare che un file che non termina con una nuova riga non è un file di testo? Ad esempio, se prendo un file di testo ASCII esistente che termina con una nuova riga e aggiungo un singolo byte 0x41(ASCII 'A'), tecnicamente non è più un file di testo? In tal caso, suggerirei di enfatizzare questo punto poiché è una specie di definizione non intuitiva; in caso contrario, un leggero cambiamento nella formulazione potrebbe aiutare a evitare la confusione.
David Z,

2
@DavidZ: questa è la definizione standard di un file di testo in Unixland. IIRC è persino in POSIX da qualche parte.
Kevin,

1
@Kevin Interessante, non l'avevo mai sentito prima. Bene, anche se è standard, penso che non sia intuitivo.
David Z,

15

Non credo sia possibile con il echocomando, utilizzare invece il seguente sedapproccio:

sed -i '$ s/$/abc/' file.txt
  • -i- modifica il file sul posto
  • $ - indica l'ultimo record / riga
  • s/$/abc/- sostituire la fine della linea $con sottostringa abc(per l'ultimo record)

2
Si noti che "sul posto" non significa davvero sul posto. Significa "scrivere il contenuto modificato in un file con nome temporaneo accanto al file esistente e quindi sostituirlo". Puoi dimostrarlo osservando gli inode condate >file; ls -i file; sed -i 's/201/ZZZ/' file; ls -i file
roaima il

@roaima, sono consapevole che sed sta cambiando il numero di inode.
RomanPerekhrest,

2
Pensavo che lo saresti stato, ma ero preoccupato del fatto che, con la tua enfasi sull'inplace in the night, penso che potesse essere usato per evitare il doppio utilizzo dello spazio su disco, ad esempio con un file di grandi dimensioni.
roaima,

@roaima, la notte pensa -> potrebbe pensare ...
RomanPerekhrest il

13

Supponendo che il file non finisca già con una nuova riga e si desideri semplicemente aggiungere altro testo senza aggiungerne uno, è possibile utilizzare l' -nargomento, ad es.

echo -n "some text here" >> file.txt

Tuttavia, alcuni sistemi UNIX non forniscono questa opzione; in tal caso è possibile utilizzare printf, ad es

printf %s "some text here" >> file.txt

(l' %sargomento iniziale è quello di difendersi dal testo aggiuntivo che %contiene caratteri di formattazione)

Da man echo(su macOS High Sierra):

-n

Non stampare il carattere di nuova riga finale. Ciò può essere ottenuto anche aggiungendo '\c'alla fine della stringa, come avviene con i sistemi compatibili iBCS2. Si noti che questa opzione e l'effetto di '\c'sono definiti dall'implementazione in IEEE Std 1003.1-2001 ("POSIX.1") come modificato dal Cor. 1-2002. Le applicazioni che mirano alla massima portabilità sono fortemente incoraggiate a utilizzare printf(1)per sopprimere il carattere newline.


E ovviamente non si esaurisce con un ritorno a capo. echo -nnon metterebbe una nuova riga alla fine di abc, ma abcsarebbe comunque preceduto da una nuova riga, che è ciò che l'utente vuole evitare.
Kusalananda

@Kusalananda La mia risposta è stata più basata sul presupposto che l'OP avrebbe cercato di cambiare il loro processo in modo tale che lo spurio \nnon si presentasse in primo luogo. Altre opzioni sono migliori, soprattutto quando non comportano la necessità di riscrivere l'intero file ogni volta che si verifica una modifica (che può diventare piuttosto lenta ed essere eseguita in tempo polinomiale se eseguita ripetutamente).
soffice

9

Se hai il truncatecomando e il tuo file di testo ha NL come ultimo carattere, puoi rimuoverlo e quindi aggiungere il tuo testo in questo modo:

truncate --size -1 file.txt
echo "abc" >>file.txt

(Nota che truncatenon importa nulla del contenuto del file, e in questo esempio riduce semplicemente la dimensione del file di un byte. Se il tuo ultimo carattere non è un singolo byte, cioè è un carattere "wide" multi-byte, introdurrai la corruzione.)


5

Quello che vuoi è aggiungerlo alla fine dell'ultima riga, quindi appena prima del delimitatore dell'ultima riga, quindi appena prima dell'ultimo carattere del file.

Con ksh93, puoi fare:

echo abc 1<> file >#((EOF - 1))

Dov'è 1<>l'operatore standard per aprire un file in modalità lettura + scrittura (e, soprattutto, senza troncamento ) su stdout ed >#((...))è un operatore di ricerca specifico per ksh93 (qui per cercare prima dell'ultimo byte). Nota che echoscrive abc<newline>dove asovrascrive la nuova riga che era lì e echoaggiunge la sua nuova riga.

L' zshequivalente:

zmodload zsh/system
{sysseek -w end -u 1 -1 && echo abc} 1<> file

Anche se per un equivalente più esatto, dovresti anche stampare un messaggio di errore in caso di mancata ricerca:

zmodload zsh/system
if sysseek -w end -u 1 -1; then
  echo abc
else
  syserror -p "$0: $LINENO: seek: "
fi 1<> file

-1

Probabilmente un UUOC ma potresti anche fare:

echo "$(cat file.txt)abc" >file.txt

Come sottolinea Gilles, questo comando è limitato:

Funziona principalmente, ma non se a volte c'è una riga vuota alla fine del file e una riga vuota immediatamente prima. Ad esempio un file con un numero fisso di righe, in cui l'ultima riga è inizialmente vuota e viene estesa nel tempo e talvolta l'ultima riga potrebbe essere vuota.

Inoltre cat, fai attenzione a non utilizzare file che non conosci:

Conclusione :

Usa sed


2
Funziona principalmente, ma non se a volte c'è una riga vuota alla fine del file e una riga vuota immediatamente prima. Ad esempio un file con un numero fisso di righe, in cui l'ultima riga è inizialmente vuota e viene estesa nel tempo e talvolta l'ultima riga potrebbe essere vuota.
Gilles 'SO- smetti di essere malvagio' il

Devo cancellarlo? Sicuramente penso che Roman / la tua risposta sia la strada giusta da percorrere, ma so che personalmente mi piace vedere delle alternative e OP ha chiesto echo: p
jesse_b

1
Anche questo mette l'intero file sulla riga di comando
n.caillou

@ n.caillou eh? Questo non stampa nulla su STDOUT.
jesse_b,

2
Bene, nessuna di queste vulnerabilità è realmente correlata cat, ma a problemi con sequenze di escape arbitrarie inviate al terminale.
ilkkachu,
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.