Ich habe ein einfaches Shell-Skript, das nachfolgende Leerzeichen aus einer Datei entfernt. Gibt es eine Möglichkeit, dieses Skript kompakter zu gestalten (ohne eine temporäre Datei zu erstellen)?
sed 's/[ \t]*$//' $1 > $1__.tmp
cat $1__.tmp > $1
rm $1__.tmp
Vielen Dank an codaddict für den Hinweis auf die -i
Möglichkeit.
Der folgende Befehl löst das Problem in Snow Leopard
sed -i '' -e's/[ \t]*$//' "$1"
Sie können die In-Place-Option -i
Von sed
für Linux und Unix verwenden:
sed -i 's/[ \t]*$//' "$1"
Beachten Sie, dass der Ausdruck nachfolgende t
unter OSX löscht (Sie können gsed
verwenden, um dieses Problem zu vermeiden). Es kann sie auch auf BSD löschen.
Wenn Sie nicht gsed haben, finden Sie hier die korrekte (aber schwer zu lesende) Sed-Syntax unter OSX:
sed -i '' -E 's/[ '$'\t'']+$//' "$1"
Drei in Anführungszeichen gesetzte Zeichenfolgen werden letztendlich zu einem einzigen Argument/Ausdruck verkettet. Es gibt keinen Verkettungsoperator in bash, Sie platzieren einfach Zeichenfolgen nacheinander ohne Leerzeichen dazwischen.
Das $'\t'
Wird in bash als literales Tabulatorzeichen aufgelöst (unter Verwendung von ANSI-C-Anführungszeichen ), sodass das Tabulatorzeichen korrekt in den Ausdruck eingebunden wird.
Zumindest bei Mountain Lion wird durch die Antwort von Viktor auch das Zeichen 't' am Ende einer Zeile entfernt. Das folgende behebt das Problem:
sed -i '' -e's/[[:space:]]*$//' "$1"
Am besten zitieren Sie auch $ 1:
sed -i.bak 's/[[:blank:]]*$//' "$1"
var1="\t\t Test String trimming "
echo $var1
Var2=$(echo "${var1}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
echo $Var2
Für diejenigen, die nach Effizienz suchen (viele zu verarbeitende Dateien oder große Dateien), die +
Wiederholungsoperator anstelle von *
beschleunigt den Befehl mehr als zweimal.
Mit GNU sed:
sed -Ei 's/[ \t]+$//' "$1"
sed -i 's/[ \t]\+$//' "$1" # The same without extended regex
Ich habe auch schnell ein anderes Benchmarking durchgeführt: mit [ \t]
anstatt [[:space:]]
beschleunigt den Prozess ebenfalls erheblich (GNU sed v4.4):
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
Ich habe ein Skript in meinem .bashrc, das unter OSX und Linux funktioniert (nur 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
}
dazu füge ich hinzu:
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
}
Nur zum Spaß:
#!/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