신비스럽게 실패한 탭의 간단한 sed 교체


43

이것은 매우 간단해야하지만 어떤 이유로 든 작동하지 않습니다.

sed -i.bak -E 's/\t/  /' file.txt

탭 문자를 바꾸는 대신 t문자를 바꿉니다 . 나는 내가 인용 할 수있는 등을 생각할 수있는 이것에 대한 모든 변형을 시도했다. 나는 구글을 검색했고 다른 사람들이 비슷한 표현을 사용하는 것을 발견 했으며 그것들이 효과가있는 것처럼 보였다.

이것은 -EOS X입니다. 나는 실패가 OS X의 이상한 기발한 결과라고 생각 sed했기 때문에 Ruby없이 ()없이 시도했지만 -i동일한 결과를 얻었습니다.

ruby -pe '$_.gsub!(/\t/,"  ")' < file.txt > file.new

OS X 및 iTerm에서 Bash 3.2.51을 사용하고 있지만 그중 어떤 것이 얼마나 관련성이 있는지 알 수는 없습니다. 이상한 환경 변수를 설정하지 않았지만 관련성이 있다고 생각되는 것을 게시 할 수는 있습니다.

무엇이 잘못 될 수 있습니까?

UPDATE : 나는 다른 실수를해야합니다 아니면 내가 루비 버전을 시도 할 때 질이 그것을 지적하기 때문에, 오타 않는 일을 (내가 한 결코 그 잘못 나를 조종 없었다!). 무슨 일이 있었는지 잘 모르겠지만, 그것이 나의 실수 였을 것입니다.


5
명령문 의 \tin을 탭 키가 어디에 있고 제어 키이며 함께 누르는 것으로 바꾸어야 할 수도 있습니다. sedCTRL-V<TAB><TAB>CTRL-Vv
unxnut

루비도 잘못된 답변을 얻는다면 정규 표현식 라이브러리 일 수 있습니다. (두 명령을 모두 테스트했으며 둘 다 탭을 공백으로 바꿉니다.) 그렇다면 Gnu sed를 설치하면 올바른 라이브러리도 설치되기를 바랍니다.
ctrl-alt-delor

답변:


63

\tsed의 탭 문자 구문 은 표준이 아닙니다. 이스케이프는 GNU sed 확장 입니다. 많은 사람들이 GNU sed를 사용하기 때문에 온라인에서이 예제를 사용하는 많은 예제를 찾을 수 있습니다 (비 임베디드 Linux의 sed 구현). 그러나 다른 * BSD sed와 마찬가지로 OS X sed\t 는 탭을 지원하지 않으며 대신 \t백 슬래시 뒤에 의미를 부여합니다 t.

다음과 같은 많은 솔루션이 있습니다.

  • 리터럴 탭 문자를 사용하십시오.

    sed -i.bak 's/  /  /' file.txt
    
  • 사용 tr또는 printf탭 문자를 생성 할 수 있습니다.

    sed -i.bak "s/$(printf '\t')/  /" file.txt
    sed -i.bak "s/$(echo a | tr 'a' '\t')/  /" file.txt
    
  • 백 슬래시 이스케이프를 허용하는 bash의 문자열 구문을 사용하십시오 .

    sed -i.bak $'s/\t/  /' file.txt
    
  • Perl, Python 또는 Ruby를 사용하십시오. 게시 한 Ruby 스 니펫이 작동합니다.


스크립트에 포함 된 sed 스크립트 ...sed( -f옵션을 통해 사용 )의 경우 리터럴 탭 문자가 유일한 가능성 인 것 같습니다. vim으로 이것을 편집 할 때 set noexpandtab중요합니다.
Tobias

경고 : 동료가 뒤에서 돌아와서 나중에 스크립트를 해제하도록하려면 "리터럴 탭 문자"기술 만 사용하십시오. tr동료가 스크립트를 읽을 때 얼굴을 찌르도록 하려면이 기술 만 사용 하십시오.
Bruno Bronosky

두 번째 큰 따옴표는 두 번째 코드 블록에 잘못 배치 되었습니까? 현재 작은 따옴표를 현재 위치로 옮겨야했습니다.
Ellen Spertus

bash 문자열 구문에 대한 링크 주셔서 감사합니다 ... 나는 몰랐다 (그리고 이것이 최선의 옵션 인 IMHO).
levigroker

sed $'s/<regex>/\t/' file.txt삽입을 위해 작동하지만 $정규식의 일부를 대체에 포함하려고하면 스크립트가 깨지는 것 같습니다 sed $'s,\(ontology/[0-9]\+\),\t\txxx\1xxx\t\t,'. \1bash의 문자열 구문 을 사용할 때 와 동등한 것이 있습니까? 편집 : xxx <U + 231C> xxx 중간에 U + 231C 유니 코드 문자가 있어야합니다.
Josh

14

배쉬 특정 사용 을 인용 하므로 실제 탭 문자가 나오지도 아닌 이스케이프 시퀀스에 전달되는 것을 당신이 C에서와 같은 문자열을 사용할 수 있습니다 :

sed -i.bak -E $'s/\t/  /' file.txt

1
다른 사람들이 그것에 대한 자세한 정보를 찾으려면 "ANSI-C"라고도합니다.
wisbucky 2016 년

2
bourne 쉘에서 작동하는 것으로 보이며 비 bash UNIX에서도 작동합니다. csh-variants에서는 작동하지 않습니다.
jornane

1

언급 된 바와 같이, 모든 sed구현 \t이 수평 탭 의 표기법을 지원하는 것은 아니다 .

다음을 통해 쉽게 대체 할 수 있습니다.

 perl -pi.old -e 's{\t+}{ }g' file.txt

원본 파일을 "* .old"로 유지하는 인시 추 교체를 수행합니다. Perl은 고전 /을 위한 대체 구분 기호를 사용 하여 표현을 훨씬 더 읽기 쉽게 만듭니다 (즉, "이쑤시개 이완"증후군이 없음).

+탭 문자 중 하나 이상 반복 교체가 말합니다. g수정은 각 행의 끝을 통해 글로벌 대체 할 수 있습니다.


1
sed -i $'s/\t/  /g' file.txt 

OS X에서 저에게 효과적이며 항상 리눅스에서 사용하는 것과 동일한 명령입니다.


이것은 모든 행의 모든 ​​탭을 대체하지만 OP는 첫 번째 탭만 사용하려고합니다 (사용하는 명령으로 판단).
Kusalananda

0

echo내부 에서도 사용할 수 있습니다 sed.

sed -i "s/$(echo '\t')//g"


참고 echo '\t'것이다 단지 출력 \t의 일부 포탄 '구현을 echo.
Kusalananda

0

OS X의 것보다 더 강력하고 sed(지원하는 \t것 이상) 원하는 경우 GNU sed를 설치하십시오 .


루비에서도 작동하지 않기 때문에 OS X sed가 문제 라고 결론 내릴 이유가 확실하지 않습니다 . 이것이 문제라고 믿을만한 이유가 있습니까? 문제를 해결할 것이라고 생각할만한 이유가 있다면 GNU sed를 설치하게되어 기쁘지만, 거의 배제한 것 같습니다.
iconoclast

Ruby를 사용하면 하나의 백 슬래시 만 사용해야합니다.ruby -pe '$_.gsub!(/\t/," ")' < file.txt
vinc17

0

이 요구 괜찮 경우 bash또는 zsh쉘로, 다음이 내가 생각할 수있는 가장 쉬운 솔루션입니다 :

sed "s/$(echo -n -e "\t")/ /" file.txt

그러나 POSIX에서는 echo플래그 ( -n-e)가 정의되어 있지 않으므로 POSIX 준수 셸에서는 이러한 플래그를 이해하지 않아도되지만 호환성을 위해 많은 것이 필요합니다.


-1

나는 누구도 매우 간단한 해결책을 제안하지 않은 것에 놀랐습니다 sed -i.bak -E 's/\\\t/ /' file.txt .

sed가 모든 것을 대체 할 때 정규 표현식에서 \ t 문자를 사용하려고한다는 것을 이해할 수 있도록 탈출 (즉, 3 \ s)을 이스케이프 처리해야합니다 ...


왜 세 개의 백 슬래시를 사용해야합니까?
Michael Homer

3
나는 GNU를 사용하는 경우 sed, 하나는 \ 더 이스케이프가 필요 없기 때문에, 충분하다. 문제는 BSD sed가 탭에 대해이 구문을 지원하지 않는다는 것입니다.
iconoclast

엘 캐피 탄에서는 작동하지 않습니다.
Franklin Yu

-4

이것은 나를 위해 일했습니다.

sed -e 's / [\ t] / / g'


3
GNU를 사용하기 때문 sed입니다. 이것은 OP가 사용하는 것이 아닙니다.
Kusalananda
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.