sed로 후행 공백을 제거하는 방법은 무엇입니까?


113

파일에서 후행 공백을 제거하는 간단한 셸 스크립트가 있습니다. 임시 파일을 만들지 않고이 스크립트를 더 압축 할 수있는 방법이 있습니까?

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

2
mv대신 사용할 수 있습니다 . 어쨌든 왜 그렇게 사용 하고 있습니까? 왜 사용하지 않습니까? catrmcatcp
추후 공지가있을 때까지 일시 중지되었습니다.

1
이 질문에서 배운 지식을 사용하여 후행 공백을 재귀 적으로 제거하는 쉘 스크립트 를 만들었 습니다 .
David Tuite 2013-08-23

1
Windows에서 sed의 버그로 인해 MinGW를 사용할 때 솔루션이 실제로 더 좋습니다. stackoverflow.com/questions/14313318/…
Cody Piersall 2014


을 사용 cat하여 원본 파일을 덮어 쓰는 대신 원본 파일 mv의 데이터를 실제로 대체합니다 (즉, 하드 링크가 깨지지 않음). sed -i많은 솔루션에서 제안 된대로 사용하면 그렇게되지 않습니다. IOW, 당신이하는 일을 계속하십시오.
William Pursell

답변:


157

Linux 및 Unix -i의 경우 in place 옵션 을 사용할 수 있습니다 sed.

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

표현식은 tOSX에서 후행을 삭제합니다 ( gsed이 문제를 방지하기 위해 사용할 수 있음 ). BSD에서도 삭제할 수 있습니다.

gsed가없는 경우 OSX에서 올바른 (하지만 읽기 어려운) sed 구문이 있습니다.

sed -i '' -E 's/[ '$'\t'']+$//' "$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는 농담이 아닙니다. GNU sed를 사용하지 않는 한 완전히 망가졌습니다 (다른 많은 방법으로 망가짐)
Good Person

59

적어도 Mountain Lion에서 Viktor의 대답은 줄 끝에있을 때 문자 't'도 제거합니다. 문제를 해결하는 다음 수정 사항 :

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

1
내가 나오지도 원 -E나타내는 "확장 (현대) 정규 표현식"
자레드 벡

OS X의 매력처럼 작동합니다. 감사합니다.
jww

1
codaddict의 대답은 OS X (현재 macOS)에서 동일한 문제가 있습니다. 이것이이 플랫폼에서 유일한 솔루션입니다.
Franklin Yu

sedEl Capitan의 @JaredBeck Mine 은 그렇지 않았습니다.
Franklin Yu

19

-i옵션 을 제안 해 주신 codaddict에게 감사드립니다 .

다음 명령은 Snow Leopard의 문제를 해결합니다.

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


7
@acrollet이 말한 것처럼 \tGNU sed 이외의 sed와 함께 사용할 수 없으며 리터럴 문자로 해석됩니다 t. 명령이 작동하는 것처럼 보입니다. 아마도 파일의 후행 공백이나 t문장 끝에 TAB이 없기 때문일 것입니다 . ''백업 접미사를 지정하지 않고 사용 하는 것은 권장되지 않습니다.
Scrutinizer 2013 년


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

효율성 (처리 할 많은 파일 또는 대용량 파일)을 찾는 +사용자의 경우 대신 반복 연산자를 *사용하면 명령이 두 배 이상 빨라집니다.

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다른 사람이 이미 언급 한 것을 옵션은 단연코 가장 간단하고 sanest 하나입니다.

더 일반적인 경우 sponge의에서 moreutils당신이 특히 매우 그것의 파일을 덮어 쓰기하여 자체 걸려 넘어에서 처리 단계를 유지하기위한 방법으로, 그 처리 결과와 파일을 대체 할 수 있습니다 : 수집, 당신이 원하는 것을 정확히 수행 작업. spongeman 페이지 를 인용하려면 :

스폰지는 표준 입력을 읽고 지정된 파일에 기록합니다. 쉘 리디렉션과 달리 스폰지는 출력 파일을 쓰기 전에 모든 입력을 흡수합니다. 이를 통해 동일한 파일에서 읽고 쓰는 파이프 라인을 구성 할 수 있습니다.

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


-1

공백이 아닌 문자가 하나 이상있는 줄에서 공백 (내 경우에는 공백 및 탭) 만 제거하려면 (이렇게하면 들여 쓴 빈 줄은 건드리지 않음) :

sed -i -r 's/([^ \t]+)[ \t]+$/\1/' "$file"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.