Как удалить конечные пробелы с помощью sed?


У меня есть простой скрипт, который удаляет конечные пробелы из файла. Есть ли способ сделать этот скрипт более компактным (без создания временного файла)?

sed 's/[ t]*$//'  > __.tmp
cat __.tmp > 
rm __.tmp
9 81

9 ответов:

вы можете использовать опцию на месте -i на sed для Linux и Unix:

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

имейте в виду, что выражение удалит трейлинг t ' s на OSX (вы можете использовать gsed чтобы избежать этой проблемы). Он также может удалить их на BSD.

если у вас нет gsed, вот правильный (но трудночитаемый) синтаксис sed на OSX:

sed -i '' -E 's/[ '$'\t'']+$//' ""

три строки в одинарных кавычках в конечном итоге объединяются в один аргумент/выражение. Нет никакой конкатенации оператор в bash, вы просто размещаете строки один за другим без пробелов между ними.

The $'\t' разрешает как литеральный символ табуляции в bash (используя ANSI-C цитирование), поэтому вкладка правильно объединена в выражение.

по крайней мере, на Mountain Lion ответ Виктора также удалит символ "t", когда он находится в конце строки. Следующие исправления этой проблемы:

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

спасибо codaddict за предложение .

следующая команда решает проблему на Snow Leopard

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

лучше всего также процитировать $1:

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

просто для удовольствия:

#!/bin/bash

FILE=

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

у меня есть скрипт на моем .bashrc, который работает под OSX и Linux (только 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=
  unamestr=$(uname)
  if [[ $unamestr == 'Darwin' ]]; then
    #specific case for Mac OSX
    sed -E -i ''  's/[[:space:]]*$//' $file
  else
    sed -i  's/[[:space:]]*$//' $file
  fi
}

к которому я добавляю:

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=

  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
}

для тех, кто ищет эффективность (много файлов для обработки, или огромные файлы), используя + оператор повторения вместо * делает команду более чем в два раза быстрее.

С GNU sed:

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

Я также быстро сравнил что-то еще: используя [ \t] вместо [[:space:]] также значительно ускоряет процесс (GNU sed v4. 4):

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

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

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

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

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

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

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

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

Чтобы только удалить пробелы( в моем случае пробелы и вкладки) из строк по крайней мере с одним символом без пробелов (таким образом, пустые отступы не затрагиваются):

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