webentwicklung-frage-antwort-db.com.de

Wie entferne ich abschließende Leerzeichen mit sed?

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
92
Viktor

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"
18
Viktor

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.

139
codaddict

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"
55
acrollet

Am besten zitieren Sie auch $ 1:

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

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
3
yolenoyer

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
}
2
Pascal T.

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
1
David Tonhofer