2010-12-14 17 views
71

Ho un semplice script di shell che rimuove spazio bianco in coda da un file. C'è un modo per rendere questo script più compatto (senza creare un file temporaneo)?Come rimuovere gli spazi bianchi finali con sed?

sed 's/[ \t]*$//' $1 > $1__.tmp 
cat $1__.tmp > $1 
rm $1__.tmp 
+1

È possibile utilizzare 'mv' invece di' cat' e 'rm'. Perché stai usando 'cat' in quel modo comunque? Perché non usare 'cp'? –

+1

Ho usato la conoscenza che ho imparato da questa domanda per creare [uno script di shell per la rimozione in modo ricorsivo spazio bianco in coda] (https://gist.github.com/dtuite/6314519). –

+1

La tua soluzione è effettivamente migliore quando usi MinGW a causa di un bug in sed su Windows: http://stackoverflow.com/questions/14313318/permission-denied-when-sed-in-place-edit-in-mingw –

risposta

17

Grazie a codaddict per suggerire l'opzione -i.

Il comando seguente risolve il problema su Snow Leopard

sed -i '' -e's/[ \t]*$//' "$1" 
+0

l'ho trovato qui, http://joemaller.com/823/quick-note-about-seds-edit-in-place-option/ – Viktor

+7

Come @acrollet dice, non è possibile usa '\ t' con sed diversa da GNU sed e viene interpretata come una letterale' t'. Il comando sembra funzionare, probabilmente perché non ci sono TAB negli spazi bianchi finali né un 't' alla fine di una frase nel tuo file. L'utilizzo di '''' senza specificare un suffisso di backup non è raccomandato. – Scrutinizer

114

È possibile utilizzare l'opzione posto in -i di sed per Linux e Unix:

sed -i 's/[ \t]*$//' "$1" 

essere a conoscenza l'espressione cancellerà trailing t 's su OS X (è possibile utilizzare gsed per evitare questo problema). Potrebbe cancellarli anche su BSD.

+0

ottengo questo errore "codice di comando non valido". – Viktor

+0

@Viktor il comando sed è buggato: necessita -i '' –

+1

Ho il seguente sulla mia macchina che non riesco ad aggiornare: 'sed: Non è una bandiera riconosciuta: i' – javaPlease42

49

Almeno in Mountain Lion, la risposta di Viktor rimuoverà anche il carattere 't' quando si trova alla fine di una riga. Il seguente correzioni problema:

sed -i '' -e's/[[:space:]]*$//' "$1" 
+1

Anche i miei hanno voluto un '-E' che indica" espressioni regolari estese (moderne) " –

+0

Funziona come un incantesimo su OS X. Grazie mille. – jww

+1

La risposta di codaddict ha lo stesso problema su OS X (ora macOS). Questa è l'unica soluzione su questa piattaforma. –

11

E 'meglio per citare anche $ 1:

sed -i.bak 's/[[:blank:]]*$//' "$1" 
4
var1="\t\t Test String trimming " 
echo $var1 
Var2=$(echo "${var1}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') 
echo $Var2 
+1

Ehi, è proprio quello di cui avevo bisogno! Le altre soluzioni sed pubblicate hanno avuto problemi di integrazione con una piping (e piped e piped ...) assegnazioni variabili nel mio script bash, ma le tue hanno lavorato fuori dagli schemi. –

1

Solo per divertimento:

#!/bin/bash 

FILE=$1 

if [[ -z $FILE ]]; then 
    echo "You must pass a filename -- exiting" >&2 
    exit 1 
fi 

if [[ ! -f $FILE ]]; then 
    echo "There is not file '$FILE' here -- exiting" >&2 
    exit 1 
fi 

BEFORE=`wc -c "$FILE" | cut --delimiter=' ' --fields=1` 

# >>>>>>>>>> 
sed -i.bak -e's/[ \t]*$//' "$FILE" 
# <<<<<<<<<< 

AFTER=`wc -c "$FILE" | cut --delimiter=' ' --fields=1` 

if [[ $? != 0 ]]; then 
    echo "Some error occurred" >&2 
else 
    echo "Filtered '$FILE' from $BEFORE characters to $AFTER characters" 
fi 
1

Ho uno script nel mio .bashrc che funziona sotto OSX e Linux (solo bash!)

function trim_trailing_space() { 
    if [[ $# -eq 0 ]]; then 
    echo "$FUNCNAME will trim (in place) trailing spaces in the given file (remove unwanted spaces at end of lines)" 
    echo "Usage :" 
    echo "$FUNCNAME file" 
    return 
    fi 
    local file=$1 
    unamestr=$(uname) 
    if [[ $unamestr == 'Darwin' ]]; then 
    #specific case for Mac OSX 
    sed -E -i '' 's/[[:space:]]*$//' $file 
    else 
    sed -i 's/[[:space:]]*$//' $file 
    fi 
} 

a cui aggiungo:

SRC_FILES_EXTENSIONS="js|ts|cpp|c|h|hpp|php|py|sh|cs|sql|json|ini|xml|conf" 

function find_source_files() { 
    if [[ $# -eq 0 ]]; then 
    echo "$FUNCNAME will list sources files (having extensions $SRC_FILES_EXTENSIONS)" 
    echo "Usage :" 
    echo "$FUNCNAME folder" 
    return 
    fi 
    local folder=$1 

    unamestr=$(uname) 
    if [[ $unamestr == 'Darwin' ]]; then 
    #specific case for Mac OSX 
    find -E $folder -iregex '.*\.('$SRC_FILES_EXTENSIONS')' 
    else 
    #Rhahhh, lovely 
    local extensions_escaped=$(echo $SRC_FILES_EXTENSIONS | sed s/\|/\\\\\|/g) 
    #echo "extensions_escaped:$extensions_escaped" 
    find $folder -iregex '.*\.\('$extensions_escaped'\)$' 
    fi 
} 

function trim_trailing_space_all_source_files() { 
    for f in $(find_source_files .); do trim_trailing_space $f;done 
} 
-1

A soltanto spazi bianchi striscia (nei miei spazi casi e tabulazioni) da linee con almeno un carattere non di spaziatura (in questo modo le linee indentate vuote non sono toccati):

sed -i -r 's/([^ \t]+)[ \t]+$/\1/' "$file" 
1

per chi cerca l'efficienza (molti file da elaborare, o file di grandi dimensioni), utilizzando l'operatore + ripetizione anziché * rende il comando di più di due volte più veloce.

Con GNU sed:

sed -Ei 's/[ \t]+$//' "$1" 
sed -i 's/[ \t]\+$//' "$1" # The same without extended regex 

Ho anche subito benchmark qualcos'altro: usando al posto del [ \t][[:space:]] anche accelera in modo significativo il processo (GNU v4.4 sed):

sed -Ei 's/[ \t]+$//' "$1" 

real 0m0,335s 
user 0m0,133s 
sys 0m0,193s 

sed -Ei 's/[[:space:]]+$//' "$1" 

real 0m0,838s 
user 0m0,630s 
sys 0m0,207s 

sed -Ei 's/[ \t]*$//' "$1" 

real 0m0,882s 
user 0m0,657s 
sys 0m0,227s 

sed -Ei 's/[[:space:]]*$//' "$1" 

real 0m1,711s 
user 0m1,423s 
sys 0m0,283s 
Problemi correlati