sedで末尾の空白を削除するにはどうすればよいですか?


113

ファイルから末尾の空白を削除する単純なシェルスクリプトがあります。(一時ファイルを作成せずに)このスクリプトをよりコンパクトにする方法はありますか?

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

2
およびのmv代わりに使用できます。なんでとにかくそんなに使ってるの?なぜ使用しないのですか?catrmcatcp
追って通知があるまで一時停止。

1
この質問から学んだ知識を使用して、末尾の空白を再帰的に削除するためのシェルスクリプトを作成しまし
David Tuite 2013

1
:MinGWのを使用しているとき、あなたのソリューションが原因のWindows上でのsedのバグのため、実際に優れているstackoverflow.com/questions/14313318/...
コーディPiersall


を使用catするmvと、実際に元のファイルのデータが置き換えられるのではなく、元のファイルが上書きされます(つまり、ハードリンクが壊れることはありません)。sed -i多くのソリューションで提案されているように使用しても、それはできません。IOW、あなたがしていることを続けてください。
ウィリアムパーセル

回答:


157

LinuxおよびUnixのin placeオプション-iを使用できますsed

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

式はtOSXの末尾のを削除することに注意してください(gsedこの問題を回避するために使用できます)。BSDでも削除される場合があります。

gsedを使用していない場合は、OSXでの正しい(ただし読みにくい)sed構文を以下に示します。

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

単一引用符で囲まれた3つの文字列は、最終的に1つの引数/式に連結されます。bashには連結演算子はなく、間にスペースを入れずに文字列を次々に配置するだけです。

$'\t'bashでリテラルのタブ文字として解決さは、(使用して引用ANSI-Cのタブが正しく表現に連結されるように、)。


1
:私は、私は更新できない私のマシン上で、次の取得 sed: Not a recognized flag: i
javaPlease42

2
うーん。また、後続の「t」をすべて削除するという意味でバグがあります:)
Good Person

2
「sed:認識されないフラグ:i –」これはOSXで発生します。Macでは、-iの後にバックアップファイルの拡張子を追加する必要があります。例:sed -i .bak 's / [\ t] * $ //' $ 1
Aimon Bustardo

1
@GoodPerson冗談ではなかった場合は、t:) をエスケープするのを忘れている可能性\tがあります。
Sean Allred

2
@SeanAllredは冗談ではありません。GNUsedを使用している場合を除き、完全に壊れています(他の多くの方法で壊れています)
Good Person

59

少なくともマウンテンライオンでは、Viktorの回答は、行の最後にある文字「t」も削除します。この問題を解決する次の修正:

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

1
私のsedは、-E「拡張(モダン)正規表現」を示すものも欲しかった
Jared Beck

OS Xの魅力のように動作します。ありがとうございました。
jww

1
codaddictの答えはOS X(現在はmacOS)でも同じ問題があります。これは、このプラットフォームでの唯一のソリューションです。
フランクリンユー

sedEl Capitanの@JaredBeck Mine にはありませんでした。
フランクリンユー

19

-iオプションを提案してくれたcodaddictに感謝します。

次のコマンドはSnow Leopardの問題を解決します

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

私はここでこれを見つけました、joemaller.com / 823 / quick
Viktor

7
@acrolletが言うように、\tGNU sed以外のsed では使用できず、リテラル文字として解釈されtます。コマンドは機能しているように見えますが、おそらくtファイルの末尾の空白や文の終わりにTABがないためです。''バックアップサフィックスを指定せずに使用することはお勧めしません。
Scrutinizer 2013年

13

$ 1も引用するのが最善です。

sed -i.bak 's/[[:blank:]]*$//' "$1"

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

1
ねえ、それは私が必要としていたことだ!投稿された他のsedソリューションには、bashスクリプトのパイプ(およびパイプとパイプ)変数の割り当てとの統合に関する問題がありましたが、あなたの箱はそのまま使用できました。
Eric L.

4

OSXとLinuxで動作する.bashrcにスクリプトがあります(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
}

私が追加したもの:

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
}

3

効率(多くのファイルを処理する、または巨大なファイル)を探す場合は、+代わりに反復演算子を使用します。*は、すると、コマンドが2倍以上速くなります。

GNU sedの場合:

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

私はすぐに別のベンチマークも行いました。[ \t]代わりに使用すると[[:space:]]、プロセスが大幅にスピードアップします(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

1

ちょうど楽しみのために:

#!/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

0

の特定のケースではsed-i他の人がすでに言及しているオプションは、最も単純で最も健全なものです。

より一般的なケースでspongeは、moreutilsコレクションから、あなたが望むことを正確に実行します:これにより、ファイルを処理した結果にファイルを置き換えることができます。取りかかっている。spongemanページを引用するには:

スポンジは標準入力を読み取り、それを指定されたファイルに書き込みます。シェルリダイレクトとは異なり、スポンジは出力ファイルを書き込む前にすべての入力を吸収します。これにより、同じファイルを読み書きするパイプラインを構築できます。

https://joeyh.name/code/moreutils/


-1

少なくとも1つの非空白文字を含む行から空白(私の場合はスペースとタブ)のみを削除するには(この方法で空のインデントされた行は変更されません):

sed -i -r 's/([^ \t]+)[ \t]+$/\1/' "$file"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.