대소 문자를 구분하지 않는 검색 및 sed로 대체


81

SED를 사용하여 로그 파일에서 텍스트를 추출하려고합니다. 너무 많은 문제없이 검색 및 바꾸기를 수행 할 수 있습니다.

sed 's/foo/bar/' mylog.txt

그러나 검색시 대소 문자를 구분하지 않고 싶습니다. 내가 검색 한 내용 i에서 명령 끝에 추가 하면 작동 하는 것처럼 보입니다 .

sed 's/foo/bar/i' mylog.txt

그러나 이것은 나에게 오류 메시지를 제공합니다.

sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'

여기서 무엇이 잘못되었으며 어떻게 수정합니까?


2
sed 사본을 업데이트 해 볼 수 있습니까? Ised 복사본에서 사용할 수없는 GNU 확장입니다.
Lazer

4
편집 : OP가 OS X에서 작동하지 않는 답변을 수락했기 때문에 OS X 자격을 통과했습니다. (다른 답변에서 알 수 있듯이 OS X의 sed는 Apple 문서와 달리 대소 문자를 구분하지 않는 일치를 지원하지 않습니다.)
danorton

1
@danorton : 감사합니다. Apple 문서가 아래의 내 대답에서 구현이 제공하지 않는 것을 약속한다는 느낌을 얻은 경우 : man sed구현과 일치합니다-대소 문자를 구분하지 않는 일치에 대한 언급이 없습니다 (실제로 지원되지 않습니다). 그렇지 않다고 주장하는 문서를 발견했다면 저희에게 알려주십시오.
mklement0 2014

1
@ mklement0, 예, 죄송합니다. Apple 문서는 sed에 대해 대소 문자를 구분하지 않는다는 주장을하지 않습니다.
danorton

1
BSD 버전이 OS X와 ​​함께 제공되는 도구의 GNU 버전 인 FWIW는 다양한 패키지 관리자에서 사용할 수 있습니다. Homebrew 를 통해 g접두사 가있는 전체 텍스트 유틸리티 제품군을 설치 했으므로 스톡 버전에서 찾을 수없는 기능을 사용 gsed하거나 gdate필요할 때 사용할 수 있습니다 .
Mark Reed

답변:


72

명확하게 말하면 : macOS 에서-Mojave (10.14) sed현재 --BSD 구현-대소 문자를 구분하지 않는 일치를 지원하지 않습니다 . 믿기 어렵지만 사실입니다. 이전 허용 대답 자체가 보여, GNU의 sed 명령 때문에 그 상태를 얻은 perl코멘트에 언급 기반 솔루션입니다.

확인하려면 펄 솔루션 과 함께 작업 외국 문자를 UTF-8을 통해,뿐만 아니라를 사용 뭔가 같은 :

perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo"
  • -C 현재 로케일이 UTF-8 기반이라고 가정하고 스트림 및 파일에 대한 UTF-8 지원을 설정합니다.
  • -Mutf8Perl에게 소스 코드 를 UTF-8 (이 경우에 전달 된 문자열 -pe) 로 해석하도록 지시합니다. 이것은 더 자세한 감사, Mark Reed에 해당하는 짧은 값입니다.-e 'use utf8;'.

(참고 것을 사용하는 것이 awk중 하나를 선택할 수 없습니다 로, awk맥 OS (즉,에 대한 것은 BWK의 AWK , 일명 BSD AWK ) 모두 로케일 전혀 모르고 것으로 보인다 - 그 tolower()toupper()(함수 외국 문자를 무시하고 sub()/ gsub()에 케이스 - 무감각 플래그가 없습니다 시작).)



69

편집자 주 :이 솔루션은 GNU 에만 적용되는 sed반면 macOS는 BSD 와 함께 제공 되기 때문에 macOS (기본 제공)에서는 작동하지 않습니다 sed.

'I'를 대문자로하십시오.

sed 's/foo/bar/I' file

2
나는 이것을 또한 보았고 그것을 시도했다 ...하지만 여전히 같은 오류 메시지가 나타납니다.
Craig Walker

15
BSD sed에는 많은 한계가있는 것 같습니다. 이 경우 PERL (즉, perl -pe 's / foo / bar / i')에서이를 수행합니다.
Wesley Rice

3
나오지도 : 1 : OS X 라이온의 기본 설치 오류를 준다 "S / foo는 / 바 / I": 대체 명령에 나쁜 플래그 'I'
벤 클레이튼

13
I접미사의 휴대용 사용하지 않습니다 sed. POSIX sed는 놀랍게도 제한적인 BRE ( Basic Regular Expressions) 만 사용합니다 . 그들은 대소 문자를 구분하지 않는 일치는 말할 것도없고 (대신 +사용해야 \{1,\}합니다) 지원하지 않습니다 . sed로 할 수있는 유일한 휴대용 방법 /[hH][eE][lL][lL][oO]/은 종종 비실용적 인를 확인하는 것 입니다.
edam

5
요구 될 것을 /gI그냥 첫 경기에서 작동합니다 othewise.
Faheem Mitha 2014

25

sedMac OS X에 대한 또 다른 해결 방법 gsed은 MacPorts 또는 HomeBrew에서 설치 한 다음 별칭을 만드는 것 sed='gsed'입니다.


gsed "s / a / b / Ig"작동합니다. 감사합니다! 좋은 답변이 왜 반대표를 받아야합니까?
Matthias M

3
이 대답은 훌륭합니다. 사용되는 brew install gnu-sed다음 내 ~ / .bash_profile을하고 추가 별명에 갔다. 감사 @davmat
ThinkBonobo

8
더 나은 방법 brew install gnu-sed --with-default-names-이것은 기본값을 재정의합니다 sed.
Mar0ux

4

나오지도 자주 묻는 질문 주소 밀접하게 관련 대소 문자를 구별하지 검색 . a) 많은 버전의 sed가 플래그를 지원하고 b) sed에서 수행하는 것이 어색하므로 awk 또는 Perl을 사용해야합니다.

그러나 POSIX sed에서 수행하기 위해 세 가지 옵션을 제안합니다 (여기에서 대체 용으로 조정 됨).

  1. 대문자로 변환하고 원래 줄을 보관 공간에 저장하십시오. 그러나 원본 콘텐츠는 인쇄 전에 복원되므로 대소 문자를 구분하지 않는 일치를 기반으로 행을 삽입하거나 추가하는 데만 유용합니다.

  2. 가능성은 FOO, Foo및 로 제한 될 수 있습니다 foo. 이것들은

    s/FOO/bar/;s/[Ff]oo/bar/
    
  3. 가능한 모든 일치 항목을 검색하려면 각 문자에 대괄호 표현식을 사용할 수 있습니다.

    s/[Ff][Oo][Oo]/bar/
    

1

의 Mac 버전은 sed약간 제한적인 것 같습니다. 이 문제를 해결하는 한 가지 방법은 사용 가능한 버전이있는 Linux 컨테이너 (Docker를 통해)를 사용하는 것입니다 sed.

cat your_file.txt | docker run -i busybox /bin/sed -r 's/[0-9]{4}/****/Ig'

15
이것은 할 수있는 특히 끔찍한 일입니다. 누군가 이것을 진지하게 생각하고 있다면 GNU sed를 로컬에 설치하십시오.
ocodo

과도하지만 유용한 일반적인 접근 방식!
YvesgereY

1

패턴 매칭을 먼저하는 경우

/pattern/s/xx/yy/g

그런 다음 I패턴 뒤에 넣기를 원합니다 .

/pattern/Is/xx/yy/g

예:

echo Fred | sed '/fred/Is//willma/g'

반환 willma; 가 없으면 I손대지 않은 문자열 ( Fred)을 반환합니다 .


2
MacO에서 나는 다음을 얻습니다 :sed: 1: "/fred/Is//willma/g": invalid command code I
Chris F Carroll

좋은 팁. 복잡한 검색에서 사용하는 방법은 다음과 같습니다 sed -r '/'"$PATTERN"'/I,${s//'$YELLOW'&'$NO_COLOR'/g;b};$q3'.. 텍스트를 인쇄하고 패턴 (대소 문자 구분 안 함)이 발견되면 텍스트를 노란색 (ansi 색상)으로 강조 표시합니다. 찾을 수없는 경우-종료 코드 3을 반환합니다.
Noam Manos

0

나는 비슷한 필요가 있었고 이것을 생각해 냈습니다.

이 명령을 사용하면 모든 파일을 간단히 찾을 수 있습니다.

grep -i -l -r foo ./* 

이것은 this_shell.sh를 제외하고 (이 명령을 this_shell.sh 라는 스크립트에 넣은 경우 ) 콘솔에 출력을 입력하여 무슨 일이 일어 났는지 확인한 다음 찾은 각 파일 이름에 sed를 사용하여 텍스트 foo를 bar로 바꿉니다. :

grep -i -l -r --exclude "this_shell.sh" foo ./* | tee  /dev/fd/2 | while read -r x; do sed -b -i 's/foo/bar/gi' "$x"; done 

수정되지 않은 파일에 대해 모든 타임 스탬프가 변경되는 것을 좋아하지 않았기 때문에이 방법을 선택했습니다. grep 결과를 제공하면 대상 텍스트가있는 파일 만 볼 수 있습니다 (따라서 성능 / 속도도 향상 될 수 있음).

사용하기 전에 파일을 백업하고 테스트하십시오. 공백이 포함 된 파일의 일부 환경에서는 작동하지 않을 수 있습니다. (?)


0

다음을 사용하여 모든 항목을 바꾸십시오. sed 's / foo / bar / gI'mylog.txt


수도를 포함하는 stackoverflow.com/a/4412964/4294399를 참조하십시오 I. 나는 또한 이것이 글로벌 교체에 대해 묻지 않기 때문에 이것이 실제로 질문에 대한 답이라고 생각하지 않습니다.
Calculuswhiz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.