이 명령은 다음과 같습니다.
echo '$$foo=bar' | sed -E "s/(\$\$foo=).*/\1$(echo hello)/"
산출:
$$foo=bar
sed
' 따옴표를 작은따옴표로 변경하고 명령을 큰따옴표로 묶으면 다음과 같습니다 .
echo '$$foo=bar' | sed -E 's/(\$\$foo=).*/\1'"$(echo hello)"'/'
원하는 결과가 출력됩니다.
$$foo=hello
그래서 나는 명백한 것을 놓치고 있지 않는 한 확장된 정규식과 따옴표에 문제가 있다고 생각합니다.
sed
명령 대체( )에서 작은따옴표와 큰따옴표를 연결하는 것이 좋은 습관 입니까sed 's/foo/'"$(command)"'/'
?sed
확장 정규 표현식을 사용하여 이중 달러 기호를 탈출하는 방법은 무엇입니까 ?
답변1
POSIX에서 할 말이 있습니다$
기본 정규식과 확장 정규식이 해석되는 방식의 차이점은 다음과 같습니다.
기본 정규 표현식(BRE):
<dollar-sign>
( )가 전체 BRE의 마지막 문자로 사용되는 경우$
앵커 포인트가 되어야 합니다. 하위 표현식의 마지막 문자로 사용되는 경우 구현 시 a를<dollar-sign>
앵커로 처리할 수 있습니다.<dollar-sign>
표현식(또는 선택적 하위 표현식)은 일치하는 문자열의 끝에 고정되어야 합니다 .<dollar-sign>
즉, 마지막 문자 뒤의 문자열 끝과 일치해야 합니다.
확장 정규식(ERE):
<dollar-sign>
( ) 괄호 표현식 외부는$
닫는 표현식 또는 하위 표현식을 문자열 끝에 고정합니다. 이러한 표현식 또는 하위 표현식은 문자열의 마지막 문자로 끝나는 시퀀스만 일치할 수 있습니다. 예를 들어 EREef$
와 ERE는 문자열 내에서 일치(ef$)
하지만 문자열 내에서는 실패하고, ERE는 작동하지만 일치하지 않습니다. 차단 식 일치가 마지막 문자로 끝나기 때문입니다.ef
abcdef
cdefab
e$f
f
e$
결론: BRE에서 $
문자는 표현식이나 하위 표현식의 마지막 문자가 아닌 한 자체적으로 일치합니다(이 경우 (하위)표현식을 줄 끝에 고정합니다). ERE에서는 $
역할이 항상 줄 끝에 고정됩니다.
당신이 사용할 때
sed -E "s/(\$\$foo=).*/\1$(echo hello)/"
귀하의 ERE(사용하는 대로 -E
)는 ($$foo=).*
다음과 같습니다. 이 표현식은안 돼요e$f
일치합니다(위의 POSIX 텍스트에도 유사한 예가 포함되어 있습니다).
주문
sed "s/\$\$foo/\$\$hello/"
문자가 표현식 끝에 있지 않기 때문에 BRE를 사용하여 $$foo
리터럴 문자열을 일치시킵니다 .$$foo
$
$
확장 정규식에서 단일 문자를 일치시키려면 \$
또는 를 사용하십시오 [$]
. 큰따옴표로 묶인 문자열로 쉘을 이스케이프하려면 \\\$
(이스케이프된 백슬래시 다음에 이스케이프된 달러 기호) 또는 [\$]
를 사용하십시오.
sed -E "s/(\\\$\\\$foo=).*/\1$(echo hello)/"
또는
sed -E "s/([\$][\$]foo=).*/\1$(echo hello)/"
\1
( 백슬래시는 뒤에 달러 기호, 백틱, 큰따옴표, 다른 백슬래시 또는 개행 문자가 오는 경우 큰따옴표로 묶인 문자열에서 이스케이프 문자 역할만 하기 때문에 의 백슬래시는 이스케이프할 필요가 없습니다 . \1
탈출하지 않고 문자 그대로의 의미 1
;여기를 참고하세요).
짧은 답변:
작은따옴표가 필요한 비트를 작은따옴표로 묶거나(그리고 이를 쉘 확장이 포함된 큰따옴표 문자열과 연결), 단일 큰따옴표 문자열로 이스케이프해야 하는 내용을 이스케이프할 수 있습니다. 그것은 맛의 문제입니다. 삽입된 문자열을 완전히 제어할 수 없는 경우 이는 코드 삽입 취약점이기 때문에 표현식에서 명령 대체를 사용하는 것이 더 걱정됩니다.
\\\$
또는[\$]
큰따옴표로 묶인 문자열입니다.\$
또는[$]
작은따옴표 문자열로.