sed에서 특정 문자를 이중 이스케이프해야 하는 이유는 무엇입니까?

sed에서 특정 문자를 이중 이스케이프해야 하는 이유는 무엇입니까?

이것은 문제를 보여주는 테스트 파일일 뿐입니다. 원래 부분은 다음과 같았습니다.

arch systemd[908]:

이제 닫는 괄호를 ":" 문자로 바꿀 수 있습니다.

krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/]/:/g
arch systemd[908::

여는 브래킷을 교체하려고 하면 작동하지 않습니다.

krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/[/:/g
sed: -e expression #1, char 7: unterminated `s' command

그런 다음 1 \ 문자로 "["를 이스케이프 처리했지만 여전히 작동하지 않습니다.

krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/[/:/g
sed: -e expression #1, char 7: unterminated `s' command

2개의 "\"를 사용하세요.

krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/\\[/:/g
arch systemd:908]:

내 질문은 다음과 같습니다.

  • 오른쪽 브래킷에서는 작동하지만 왼쪽 브래킷에서는 작동하지 않는 이유는 무엇입니까? sed 또는 bash가 이것을 읽는 방식의 차이점은 무엇입니까?
  • 오른쪽 대괄호와 잘 작동하고 전혀 이스케이프할 필요가 없는데 왼쪽 대괄호를 두 번 이스케이프해야 하는 이유는 무엇입니까?

나는 이것을 이해하고 싶습니다. 이제 이 작업을 수행하는 방법을 알고 있지만 세부 사항을 알지 못하는 것에 만족하지 않습니다.

답변1

sed이는 sed 표현식을 인용하지 않았기 때문입니다(나쁜 생각입니다. 명령을 작은따옴표로 묶는 습관을 가지세요). 이스케이프해야 하는 이유 는 정규식에서 특별한 의미를 갖고 문자 클래스를 열기 [때문입니다 (예: 또는 중 하나와 일치함). sed는 이전에 닫을 것이 없기 때문에 이 경우 문자 클래스가 닫히지 않을 것이라는 것을 알 만큼 똑똑하기 때문에 탈출할 필요가 없습니다.[[abc]abc]][

이제 sed 표현식을 인용하지 않았으므로 이는 쉘이 이를 해석하려고 시도한다는 의미입니다.앞으로에 전달합니다 sed. 따라서 쉘은 사용자의 문자를 보고 \[이스케이프되지 않은 문자를 sed에 전달합니다. 다음을 통해 이를 실제로 확인할 수 있습니다 set -x.

$ set -x
$ sed s/\[/:/g jctl.log
+ sed 's/[/:/g' jctl.log
sed: -e expression #1, char 7: unterminated `s' command

보시다시피 실행되는 실제 명령은 sed 's/[/:/g' jctl.log다음과 같습니다 sed 's/\[/:/g' jctl.log. 쉘이 이스케이프 문자를 사용했습니다. 그런 다음 sed가 종결자를 찾고 있지만 ]찾지 못하기 때문에 실패합니다. 따라서 전체 문자열을 /:/g문자 클래스의 내용으로 취급하므로 명령의 끝을 찾을 수 없기 때문에 실패합니다 s///.

두 번째 이스케이프 수준을 추가하면 쉘이 첫 번째 이스케이프 수준을 사용한 다음 여전히 이스케이프를 [sed에 전달할 수 있습니다.

$ sed s/\\[/:/g jctl.log
+ sed 's/\[/:/g' jctl.log
arch systemd:908]:

위의 출력에서 \[​​이제 sed 대신 sed가 제공되는 것을 볼 수 있습니다 [.

항상 sed 명령을 인용하면 다음 문제가 모두 사라집니다.

$ sed 's/\[/:/g' jctl.log
arch systemd:908]:

관련 정보