큰따옴표 안에 '!'를 이스케이프하세요.

큰따옴표 안에 '!'를 이스케이프하세요.

bash는 수동으로 큰따옴표를 입력합니다(https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html) 상태:

활성화되면 "!"가 큰따옴표 안에 표시되고 백슬래시로 이스케이프되지 않는 한 기록 확장이 수행됩니다. 앞에 있는 '!'의 백슬래시는 제거되지 않습니다.

왜 특별한 경우가 있습니까 !? 예를 들어 a를 이스케이프하면 $출력에 백슬래시가 표시되지 않습니다(예: echo "\$"-> $echo "\!"-> 비교 \!).

!큰따옴표 안에 텍스트만 넣으려면 어떻게 해야 하나요?

이 문제에 대한 한 가지 제한 사항은 bash 호출 형식을 쉽게 조작할 수 없다는 것입니다. 내 말은 단일 큰따옴표 문자열을 사용하여 명령을 실행하는 데 멈췄다는 것입니다. my-command "a string I generate in an external program that may contain !"

문자열이 생성되는 방식을 제어할 수 있지만 명령줄에서 분할할 수는 없습니다(예: 이와 같은 것은 "part1"\!"part2"나에게 적합하지 않습니다.)

답변1

!is를 사용하여 문자열 인쇄아니요따옴표가 없거나 작은 따옴표로 묶인 경우, C 문자열 또는 스크립트 내에서 문제가 발생합니다.

$ echo hello\!world 'hello!world' $'hello!world'
hello!world hello!world hello!world

$ echo 'echo "hello!world"' >file
$ bash file
hello!world

이 스크립트 예제는 histexpand가 기본적으로 설정되지 않은 특별한 경우입니다. 따라서 histexpand를 비활성화하면( 간단히 or set +o histexpandshopt -ou histexpand동일 set +H) 동일한 효과를 가지며 기록 확장을 피할 수 있습니다.

그러나 문자열을 여러 부분으로 분할하지 않고 (기본) 대화형 셸에서 큰따옴표로 묶인 문자열을 사용하도록 요청하고 있습니다. 음, 어떻습니까?

$ a='!'
$ echo "hello${a}world"
hello!world

역사에 대하여왜?.

왜 특별한 경우가 있는 걸까요! ?

왜냐하면 대부분의 ASCII 문자는아니요특수(내부 "):

$ printf '%s\n' "\a\b\c\d\e\f...\z \!\@\#\%     \$a \`date\` \\"

\a\b\c\d\e\f...\z \!\@\#\%     $a `date` \

관련 텍스트 출처 man bash:문자를 큰따옴표로 묶으면 기록 확장이 활성화된 경우 $, `, \ 및 !를 제외한 따옴표 안의 모든 문자의 리터럴 값이 유지됩니다.

이것은 고대 쉘에서 큰따옴표 안의 백슬래시가 작동하는 방식입니다.POSIX 사양반영:

<백슬래시>는 뒤에 다음 문자 중 하나가 오는 경우 특수 문자로 처리되는 경우에만 이스케이프 문자로서의 특별한 의미를 유지해야 합니다(이스케이프 문자(백슬래시) 참조).

$ ` " \ <줄바꿈>

답변2

!분명히 Bash는 (과거 확장을 억제하기 위해) 큰따옴표 안에 나타나는 이스케이프 백슬래시 사용을 제거하지 않습니다.허위 공격메일링 리스트.

이 행동에 대한 역사적 이유는 다음에서 언급되었습니다.이미 가지고 있는 답변이것은 실제로 Bash의 개발자와 유지관리자가 제공한 설명입니다. 버그 배쉬 인용쳇 레이미에 관한 뉴스:

참고로 '!'는 작은따옴표나 백슬래시로만 이스케이프할 수 있습니다. "!"는 POSIX.2 사양 및 전통적인 sh 동작에 따라 큰따옴표 안에 특별히 처리되는 문자 중 하나가 아니기 때문에 큰따옴표가 작동하지 않습니다.

동일한 소스에서 !큰따옴표를 처리하는 방법에 대해 설명합니다.

"set +o histexpand"를 사용하여 기록 확장을 끄거나 큰따옴표 밖에 백슬래시를 사용할 수 있습니다. 쉘이 대화형이 아닐 때는 일반적으로 히스토리 확장이 활성화되지 않으므로 스크립트에서 백슬래시를 제거하는 것은 문제가 되지 않습니다.

(동일한 진술의 일부 변형이 이 메일링 리스트에서 발견될 수 있습니다.1그리고2, C 쉘과의 관계도 언급함).

이러한 해결 방법을 사용할 수 없는 경우: 다음 질문에 대한 답변에 다양한 해결 방법이 나와 있습니다.큰 소리를 내는 방법!, 예를 들어 의 첫 번째 문자를 histchars사용할 가능성이 없는 문자로 설정하거나 동일한 변수의 세 번째 문자를 사용하여 히스토리 확장을 적용하지 않으려는 명령을 시작하는 등입니다.

관련 정보