sh 스크립트에서 sed를 사용할 때 어떤 문자를 이스케이프해야합니까?


248

다음 스크립트를 보자.

#!/bin/sh
sed 's/(127\.0\.1\.1)\s/\1/' [some file]

sh( dashhere)에서 이것을 실행하려고 하면 괄호로 인해 실패해야하며 탈출해야합니다. 그러나 백 슬래시 자체를 피할 필요 는 없습니다 (옥텟 사이 \s또는 또는 \1). 여기서 규칙은 무엇입니까? {...}또는 [...]언제 사용해야 합니까? 내가하고 도망 칠 필요가없는 목록이 있습니까?


1
다음은 SED와 함께 사용할 경로를 변환하기위한 bash 함수입니다.function sedPath { path=$((echo $1|sed -r 's/([\$\.\*\/\[\\^])/\\\1/g'|sed 's/[]]/\[]]/g')>&1) } #Escape path for use with sed
user2428118 12


듀라 렉스, sed sed
니모

답변:


281

여기에는 셸과 sed라는 두 가지 수준의 해석이 있습니다.

쉘에서 작은 따옴표 자체를 제외하고 작은 따옴표 사이의 모든 것이 문자 그대로 해석됩니다. 작은 따옴표 사이에 작은 따옴표를 효과적으로 쓸 수 있습니다 '\''(작은 따옴표, 하나의 리터럴 작은 따옴표, 열린 작은 따옴표).

Sed는 기본 정규 표현식을 사용 합니다 . BRE에서 문자 그대로 처리 $.*[\^하려면 문자 세트 ( […])를 제외하고 문자 앞에 백 슬래시를 사용 하여 문자 를 인용해야합니다 . 문자, 숫자 및 (){}+?|따옴표로 묶지 말아야합니다 (일부 구현에서 이들 중 일부를 인용하여 벗어날 수 있음). 시퀀스는 \(, \), \n, 및 일부 구현에서 \{, \}, \+, \?, \|등의 백 슬래시 + 알파벳과 숫자는 특별한 의미가 있습니다. $^일부 구현에서는 일부 위치에서 인용하지 않고 벗어날 수 있습니다 .

또한 /대괄호 표현식 외부의 정규식에 나타나려면 백 슬래시가 필요합니다 . 예를 들어 s~/dir~/replacement~또는 \~/dir~p;를 작성하여 대체 문자를 구분 기호로 선택할 수 있습니다 . BRE에 포함 시키려면 분리 문자 앞에 백 슬래시가 필요합니다. BRE에서 특별한 의미가있는 문자를 선택하고 문자 그대로 포함하려면 세 개의 백 슬래시가 필요합니다. 일부 구현에서는 다르게 동작 할 수 있으므로 권장하지 않습니다.

간단히 말해 sed 's/…/…/':

  • 작은 따옴표 사이에 정규식을 작성하십시오.
  • '\''정규 표현식에서 작은 따옴표로 끝나는 데 사용하십시오 .
  • $.*/[\]^문자 앞에만 백 슬래시를 넣으십시오 (대괄호 표현식은 제외). (기술적으로 백 슬래시를 넣지 말아야 ]하지만 대괄호 표현식 외부에서 처리 ]하고 \]다르게 구현하는 방법을 모르겠습니다 .)
  • 대괄호 표현식 내에서 -문자 그대로 처리하려면 첫 번째 또는 마지막 ( [abc-]또는 [-abc], not [a-bc]) 인지 확인하십시오 .
  • 대한 브래킷 표현 내부, ^문자 그대로 처리 할 수 있는지가되어 있는지 확인 하지 (사용 첫째 [abc^],하지 [^abc]).
  • 포함하려면 ]브라켓 표현 일치 문자 목록에서, 그것은 (또는 첫 번째 이후의 첫 번째 문자하게 ^부정 된 세트) []abc]또는 [^]abc](하지 [abc]]않고[abc\]] ).

대체 텍스트에서 :

  • &\구분 기호 (일반적으로하는 것처럼, 백 슬래시를 앞에 인용 할 필요 /)와 뉴 라인.
  • \숫자 다음에 특별한 의미가 있습니다. \뒤에 나오는 문자는 일부 구현에서 특별한 의미 (특수 문자)를 가지며, \그 뒤에 다른 문자 수단이 \c있거나 c구현에 따라 다릅니다.
  • 인수 ( sed 's/…/…/')를 작은 따옴표로 묶으 '\''면 대체 텍스트에 작은 따옴표를 넣습니다.

정규식 또는 대체 텍스트가 쉘 변수에서 온 경우

  • 정규식은 리터럴 문자열이 아닌 BRE입니다.
  • 정규 표현식에서 줄 바꿈은 다음과 같이 표현해야합니다 \n( sed패턴 공간에 줄 바꿈 문자를 추가하는 다른 코드 가 없으면 일치하지 않습니다 ). 그러나 일부 sed구현 에서는 대괄호 표현식에서 작동하지 않습니다 .
  • 대체 텍스트에서 &, \및 줄 바꿈을 인용해야합니다.
  • 구분 기호는 따옴표로 묶어야합니다 (단, 괄호 표현식은 제외).
  • 보간에 큰 따옴표를 사용하십시오 sed -e "s/$BRE/$REPL/".

실제 와일드 카드 문자 (*)를 이스케이프 처리하면 이중 백 슬래시 ( \\*)를 사용할 수 있습니다 . 예 :echo "***NEW***" | sed /\\*\\*\\*NEW\\*\\*\\*/s/^/#/
danger89

43

겪고있는 문제는 쉘 보간 및 이스케이프 때문이 아닙니다 .sed -r또는 --regexp-extended옵션 을 전달하지 않고 확장 정규 표현식 구문을 사용하려고하기 때문 입니다.

sed 라인을 다음에서 변경하십시오.

sed 's/(127\.0\.1\.1)\s/\1/' [some file]

sed -r 's/(127\.0\.1\.1)\s/\1/' [some file]

당신이 생각하는대로 작동합니다.

기본적으로 sed는 기본 정규 표현식 (그렙 스타일을 생각합니다)을 사용하며 다음 구문이 필요합니다.

sed 's/\(127\.0\.1\.1\)[ \t]/\1/' [some file]

나는이 문제를 다시 가지고 있었고, 지난번에 upvoted 한 해결책을 찾기 위해 아래로 스크롤하는 것을 잊었다. 다시 감사합니다.
isaaclw

고마워 -r옵션으로 추가 하는 것이 필자의 경우 필요했습니다.
HelloGoodbye

15

쉘 변수를 sed 표현식에 보간하지 않으려면 전체 표현식에 작은 따옴표를 사용하십시오. 백 슬래시를 포함하여 변수 사이의 모든 것이 그대로 해석되기 때문입니다.

따라서 sed가 s/\(127\.0\.1\.1\)\s/\1/그 주위에 작은 따옴표를 붙이고 싶다면 쉘이 괄호 또는 백 슬래시를 만지지 않습니다. 쉘 변수를 보간해야하는 경우 해당 부분 만 큰 따옴표로 묶으십시오. 예 :

sed 's/\(127\.0\.1\.1\)/'"$ip"'/'

이렇게하면 큰 따옴표로 이스케이프되지 않은 쉘 메타 문자를 기억하지 않아도됩니다.


을보고 싶지만 sed그대로 s/(127\.0\.1\.1)/...쉘 스크립트에 넣는 것은 작동하지 않습니다. 괄호에 닿지 않는 쉘에 대해 말하는 것은 잘못된 것 같습니다. 정교하게 질문을 편집했습니다.
detly February

3
쉘이 괄호에 닿지 않습니다. sed 가 그들을 볼 필요가 있기 때문에 당신은 backslases가 필요 합니다. sed 's/(127\.0\.1\.1)/IP \1/'나오지도보고해야하기 때문에 실패 \(\)그룹 구문을하지 않는 ().
Kyle Jones

facepalm 맨 페이지에 없지만, 내가 찾은 온라인 매뉴얼에 있습니다. 정규 표현식 라이브러리에서 정규 표현식 라이브러리를 사용하지 않아도 되었기 때문에 정규 표현식에 정상입니까?
detly February

3
전통적인 Unix 명령에는 기본 정규 표현식과 확장 정규 표현식이 있습니다. 세부 사항 . sed는 기본 정규 표현식을 사용하므로 그룹 구문에는 백 슬래시가 필요합니다. Perl과 Python은 확장 된 정규 표현식을 뛰어 넘었습니다. 주위를 파고 드는 동안 "정규 표현"이라는 말을 할 때 혼란스러워하는 덤블을 보여주는 매우 유익한 차트 를 발견했습니다 .
Kyle Jones

1
또한 작은 따옴표 안에 사용할 수없는 유일한 문자는 작은 따옴표입니다.
enzotib
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.