2014-12-04 11 views
32

Dire che ho un po 'arbitrario file di testo su più righe:Come posso rimuovere l'ultimo carattere di un file in unix?

sometext 
moretext 
lastline 

Come posso rimuovere solo l'ultimo carattere (la posta, non il ritorno a capo o nullo) del file senza il file di testo non validi?

+0

Cosa avete fatto per risolvere questo? -1 – Jotne

+2

Elencare una manciata di comandi di immondizia e di awk che tolgono l'ultimo carattere da ogni linea non si sentono terribilmente costruttivi. Heh, sapevo che mi sarei fatto male per quello. Tuttavia, non potevo lasciarmi andare nella frase "Ho provato un sacco di sed e awk, ma potevo solo spogliare l'ultimo carattere di ogni riga in una varietà di modi". – MaxPRafferty

risposta

50

Un approccio più semplice (uscite StdOut, non aggiorna il file di input):

sed '$ s/.$//' somefile 
  • $ è un indirizzo che corrisponde Sed solo l'ultima riga di input, causando la seguente funzione chiamare() da eseguire solo sull'ultima riga.
  • s/.$// sostituisce l'ultimo carattere sulla riga (in questo caso last) con una stringa vuota; cioè rimuove efficacemente l'ultimo carattere. (prima della newline) sulla linea.
    . corrisponde a qualsiasi carattere sulla linea e lo segue con $ ancore la corrispondenza alla fine della riga; si noti come l'uso di $ in questa espressione regolare sia concettualmente correlato, ma tecnicamente distinto dall'uso precedente di $ come indirizzo Sed .
  • Esempio con ingresso stdin (assume Bash, Ksh, o Zsh):

    $ sed '$ s/.$//' <<< $'line one\nline two' 
    line one 
    line tw 
    

Per aggiornamento del file di input troppo (non usare se il file di input è un link simbolico):

sed -i '$ s/.$//' somefile 

Nota:
* su OSX, che avrebbe dovuto utilizzare -i '' invece di -i; per una panoramica delle insidie ​​associate a -i, vedere la metà inferiore di my answer here.
* Se è necessario elaborare file di input di grandi dimensioni e/o prestazioni/utilizzo del disco sono una preoccupazione e si sta utilizzando utilità GNU (Linux), vedere sorontar's helpful answer.

1

Dopo un mazzo intero di giocare con diverse strategie (ed evitando sed -i o Perl), il modo migliore che ho trovato per fare questo è stato con:

sed '$! { P; D; }; s/.$//' somefile 
+0

Non sai perché eviti 'sed -i'. Questa è solo una funzione per scrivere i dati sul file. Ora hai solo l'output da monitorare. – Jotne

4

Ecco un altro utilizzando ex, che trovo non come criptico come la soluzione sed:

printf '%s\n' '$' 's/.$//' wq | ex somefile 

la $ va all'ultima riga, il s cancella l'ultimo carattere, e wq è il ben noto (per gli utenti di vi) scrittura + uscire.

1

RISPOSTA A CURA

ho creato uno script e mettere il testo all'interno sul mio desktop. Questo file di test viene salvato come "old_file.txt"

sometext 
moretext 
lastline 

In seguito ho scritto un piccolo script per prendere il vecchio file ed eliminare l'ultimo carattere nell'ultima riga

#!/bin/bash 
no_of_new_line_characters=`wc '/root/Desktop/old_file.txt'|cut -d ' ' -f2` 
let "no_of_lines=no_of_new_line_characters+1" 
sed -n 1,"$no_of_new_line_characters"p '/root/Desktop/old_file.txt' > '/root/Desktop/my_new_file' 
sed -n "$no_of_lines","$no_of_lines"p '/root/Desktop/old_file.txt'|sed 's/.$//g' >> '/root/Desktop/my_new_file' 

aprendo la new_file ho creato, mostrato l'output come segue:

sometext 
moretext 
lastlin 

mi scuso per la mia risposta precedente (non è stato letto attentamente)

+1

Si sta richiedendo di rimuovere solo l'ultimo carattere di un file, non l'ultimo carattere di ogni riga. –

+1

Mi scuso per la mia risposta non stava leggendo attentamente .. Sono stato in grado di ottenere la soluzione utilizzando una piccola sceneggiatura che ho creato. Spero che questo aiuti MaxPRafferty – repzero

1

Se l'obiettivo è quello di rimuovere l'ultimo carattere nell'ultima riga, questo awk dovrebbe fare:

awk '{a[NR]=$0} END {for (i=1;i<NR;i++) print a[i];sub(/.$/,"",a[NR]);print a[NR]}' file 
sometext 
moretext 
lastlin 

E memorizzare tutti i dati in un array, quindi stamparlo e cambiare ultima riga.

1

sed 's/.$//' filename | tee newFilename

Questo dovrebbe fare il tuo lavoro.

+1

Ciò rimuoverà l'ultimo carattere da ogni riga, non solo l'ultimo carattere dell'ultima riga. – MaxPRafferty

+0

@MaxPRafferty mio male. Pensavo che la domanda fosse rimuovere l'ultimo carattere di ogni riga – karthik339

13

truncate

truncate -s-1 file 

rimuove un (-1) caratteri dalla fine dello stesso file. Esattamente come >> si aggiungerà allo stesso file.

Il problema con questo approccio è che non mantiene una nuova riga finale se esiste.

La soluzione è:

if  [ -n "$(tail -c1 file)" ] # if the file has not a trailing new line. 
then 
     truncate -s-1 file   # remove one char as the question request. 
else 
     truncate -s-2 file   # remove the last two characters 
     echo "" >> file    # add the trailing new line back 
fi 

Questo funziona perché coda prende l'ultimo byte (non char).

Non ci vuole quasi tempo nemmeno con i file di grandi dimensioni.

Perché non sed

Il problema con una soluzione sed come sed '$ s/.$//' file è che legge l'intero file prima (prendendo a lungo con file di grandi dimensioni), allora avete bisogno di un file temporaneo (della stessa dimensione come originale):

sed '$ s/.$//' file > tempfile 
rm file; mv tempfile file 

E quindi spostare il file temp per sostituire il file.

+0

Molto bello! Non sapevo di troncare, grazie. – MaxPRafferty

+0

non accessibile in macos? – olegtaranenko

1

Solo una nota: sed rimuoverà temporaneamente il file. Quindi, se si sta tailing del file, verrà visualizzato un avviso "Nessun file o directory" finché non si riemette il comando tail.

Problemi correlati