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

다음 스크립트를 보자.

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

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



답변

여기에는 셸과 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/".

답변

겪고있는 문제는 쉘 보간 및 이스케이프 때문이 아닙니다 .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]

답변

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

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

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

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