Bash sed는 이중 달러 기호 $$ 확장 정규식을 대체합니다.

Bash sed는 이중 달러 기호 $$ 확장 정규식을 대체합니다.

이 명령은 다음과 같습니다.

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

그래서 나는 명백한 것을 놓치고 있지 않는 한 확장된 정규식과 따옴표에 문제가 있다고 생각합니다.

  1. sed명령 대체( )에서 작은따옴표와 큰따옴표를 연결하는 것이 좋은 습관 입니까 sed 's/foo/'"$(command)"'/'?

  2. sed확장 정규 표현식을 사용하여 이중 달러 기호를 탈출하는 방법은 무엇입니까 ?

답변1

POSIX에서 할 말이 있습니다$기본 정규식과 확장 정규식이 해석되는 방식의 차이점은 다음과 같습니다.

기본 정규 표현식(BRE):

<dollar-sign>( )가 전체 BRE의 마지막 문자로 사용되는 경우 $앵커 포인트가 되어야 합니다. 하위 표현식의 마지막 문자로 사용되는 경우 구현 시 a를 <dollar-sign>앵커로 처리할 수 있습니다. <dollar-sign>표현식(또는 선택적 하위 표현식)은 일치하는 문자열의 끝에 고정되어야 합니다 . <dollar-sign>즉, 마지막 문자 뒤의 문자열 끝과 일치해야 합니다.

확장 정규식(ERE):

<dollar-sign>( ) 괄호 표현식 외부는 $닫는 표현식 또는 하위 표현식을 문자열 끝에 고정합니다. 이러한 표현식 또는 하위 표현식은 문자열의 마지막 문자로 끝나는 시퀀스만 일치할 수 있습니다. 예를 들어 ERE ef$와 ERE는 문자열 내에서 일치 (ef$)하지만 문자열 내에서는 실패하고, ERE는 작동하지만 일치하지 않습니다. 차단 식 일치가 마지막 문자로 끝나기 때문입니다.efabcdefcdefabe$ffe$

결론: 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;여기를 참고하세요).

짧은 답변:

  1. 작은따옴표가 필요한 비트를 작은따옴표로 묶거나(그리고 이를 쉘 확장이 포함된 큰따옴표 문자열과 연결), 단일 큰따옴표 문자열로 이스케이프해야 하는 내용을 이스케이프할 수 있습니다. 그것은 맛의 문제입니다. 삽입된 문자열을 완전히 제어할 수 없는 경우 이는 코드 삽입 취약점이기 때문에 표현식에서 명령 대체를 사용하는 것이 더 걱정됩니다.

  2. \\\$또는 [\$]큰따옴표로 묶인 문자열입니다. \$또는 [$]작은따옴표 문자열로.

관련 정보