다음 스크립트를 보자.
#!/bin/sh
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
sh
( dash
here)에서 이것을 실행하려고 하면 괄호로 인해 실패해야하며 탈출해야합니다. 그러나 백 슬래시 자체를 피할 필요 는 없습니다 (옥텟 사이 \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"'/'
이렇게하면 큰 따옴표로 이스케이프되지 않은 쉘 메타 문자를 기억하지 않아도됩니다.