일관된 논리가 있나요?
some-command "${somevariable//some pattern/'how does this get parsed?'}"
아래에 몇 가지 결론과 독창적인 테스트를 "답변"으로 게시했지만 결코 완전한 답변은 아닙니다. Bash 매뉴얼 페이지에는 이 주제가 언급되지 않은 것 같습니다.
답변1
댓글에서 논의한 것처럼 이는 Bash 버전 간에 변경된 것 같습니다. 나는 이것이 적절한 변화라고 생각합니다 bash-4.3-alpha
(변경 로그):
ZZ. 패턴 대체 단어 확장을 사용할 때 bash는 이제 문자열 내의 따옴표가 이스케이프 문자로 작동하도록 허용하므로 따옴표를 제거하여 대체 문자열을 실행합니다. 이는 이전 버전과 호환되지 않으므로 bash 호환성 모드를 4.2로 설정하여 비활성화할 수 있습니다.
게다가 shopt -s compat42
(온라인 매뉴얼):
compat42
설정하면 bash는 패턴 대체 단어 확장에서 대체 문자열을 처리하기 위해 따옴표 제거를 사용하지 않습니다.
작은따옴표로 인용하는 예:
$ s=abc\'def; echo "'${s//\'/\'\\\'\'}'"
'abc'\''def'
$ shopt -s compat42
$ s=abc\'def; echo "'${s//\'/\'\\\'\'}'"
'abc\'\\'\'def'
$ bash --version | head -1
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
해결 방법: 대체 문자열을 변수에 넣은 다음아니요대체에 따옴표를 사용하십시오.
$ shopt -s compat42
$ qq="'\''"; s=abc\'def; echo "'${s//\'/$qq}'";
'abc'\''def'
$ qq="'\''"; s=abc\'def; echo "'${s//\'/"$qq"}'";
'abc"'\''"def'
흥미롭게도 확장이 이루어지면인용되지 않음, 모든 버전에서 교체 후 따옴표가 제거됩니다. 그게 s=abc; echo ${s/b/""}
판화야 ac
. 이는 확실히 s='a""c' ; echo ${s%x}
outputs 와 같은 다른 확장에서는 발생하지 않습니다 a""c
.
답변2
리버스 엔지니어링의 일반 규칙:
- 견적은 연결되어야 합니다(완료).
- 제안 유지(실제 교체에 포함)
- 백슬래시가 문자 앞에 나타나면 백슬래시가 유지됩니다.
- 백슬래시가 작은따옴표를 이스케이프하면 백슬래시가 유지됩니다.
- 작은따옴표 내에서도 백슬래시 백슬래시 시퀀스는 하나의 백슬래시로 줄어듭니다.
- 작은따옴표 안에 작은따옴표를 이스케이프할 수 없습니다.
- 매개변수 확장은 작은따옴표 외부에서와 마찬가지로 작은따옴표 내부에서도 동일한 방식으로 작동합니다.
- 백슬래시를 사용하여 달러 기호를 이스케이프하면 달러 기호는 그대로 유지되고 백슬래시는 제거됩니다.
그리고 결론을 내렸다:
'\''
매개변수 확장을 통해 대체 리터럴 시퀀스를 생성할 수 있는 방법은 전혀 없습니다 .- 그러나 대체 텍스트 시퀀스를 생성하는
"'\''"
것은 매우 쉽습니다 .
다음은 몇 가지 원시 테스트입니다.
[vagrant@localhost ~]$ echo "$0"
-bash
[vagrant@localhost ~]$ echo "${0//a/x}"
-bxsh
[vagrant@localhost ~]$ echo "${0//a/some long string with spaces}"
-bsome long string with spacessh
[vagrant@localhost ~]$ echo "${0//a/"quoted string"}"
-b"quoted string"sh
[vagrant@localhost ~]$ echo "${0//a/"unfinished quote}"
> wat
> }"
-b"unfinished quote}"
wat
sh
[vagrant@localhost ~]$ echo "${0//a/\"escaped quote}"
-b"escaped quotesh
[vagrant@localhost ~]$ echo "${0//a/\\escaped escape}"
-b\escaped escapesh
[vagrant@localhost ~]$ echo "${0//a/\'escaped single quote}"
-b\'escaped single quotesh
[vagrant@localhost ~]$ echo "${0//a/''}"
-b''sh
[vagrant@localhost ~]$ echo "${0//a/''''}"
-b''''sh
[vagrant@localhost ~]$ echo "${0//a/'''}"
> a'b}c"d
-b'''}"
a'bshcd
[vagrant@localhost ~]$ echo "${0//a/'''}"
> w'x}y"z
-b'''}"
w'xshyz
[vagrant@localhost ~]$ echo "${0//a/'\'\\"a test'\'}"
> ^C
[vagrant@localhost ~]$ echo "${0//a/'\''\\"a test'\'}"
-b'\''\"a test'\'sh
[vagrant@localhost ~]$ echo "${0//a/'\''\\"a test'\$0'}"
> ^C
[vagrant@localhost ~]$ echo "${0//a/\\"a test'\$0'}"
> w}x"y
-b\"a test'$0'}"
wshxy
[vagrant@localhost ~]$ echo "${0//a/\\\"a test'\$0'}"
-b\"a test'$0'sh
[vagrant@localhost ~]$ echo "${0//a/\\\"a test'\\'$0'}"
> ^C
[vagrant@localhost ~]$ echo "${0//a/\\\"a test'\\$0'}"
-b\"a test'\-bash'sh
[vagrant@localhost ~]$
답변3
실험을 통해 다음 구문을 사용하면 GNU bash 버전 5.0.11(1) 릴리스(x86_64-pc-linux-gnu)에서 작은따옴표를 큰따옴표로 변환할 수 있다는 것을 발견했습니다...
text="aaa'bbb'ccc"; echo "${text//$"'"/$'"'}"
밝혀지다...
aaa"bbb"ccc
작은따옴표 패턴은 큰따옴표로 묶어야 하며, 큰따옴표 대체 패턴은 작은따옴표로 묶어야 합니다.
다음과 같은 관련 쇼핑 기록이 있습니다.
extquote
If set, $'string' and $"string" quoting is performed within
${parameter} expansions enclosed in double quotes. This option
is enabled by default.