다음 6개의 파일이 제공됩니다.
$ touch 'sec*et' 'sec\*et' 'sec\et' secet secret 'sec\ xxx et'
왜전역 확장을 위해 인용되지 않은 변수의 백슬래시파일 만 일치하시겠습니까 sec\*et
?
$ v="sec\*et" ; ls $v
'sec\*et'
$ v='sec\*et' ; ls $v
'sec\*et'
<백슬래시>는 이스케이프 문자라는 특별한 의미를 유지해야 합니다. 뒤에 다음 문자 중 하나가 올 때만 특별한 것으로 간주됩니다.
$
`
"
\
<newline>
그리고배쉬 매뉴얼:
$
백슬래시는 ' ', '`
', '"
', '\
' 또는 개행 문자 중 하나가 뒤에 오는 경우에만 특별한 의미를 유지합니다 . 큰따옴표 내에서 이러한 문자 중 하나 뒤에 오는 백슬래시가 제거됩니다. 특별한 의미가 없는 선행 백슬래시 문자는 변경되지 않습니다.
변수의 백슬래시(별표 앞)가 리터럴 백슬래시라는 것을 알고 있습니다.
$ v='sec\*et' ; printf '%s' "$v" | hexdump -C
00000000 73 65 63 5c 2a 65 74 |sec\*et|
00000007
*
그러나 리터럴 백슬래시 이후 와일드카드가 왜 특별한 의미를 잃는지 이해할 수 없습니다 .
내가 이해하는 세 가지:
*
(A) 인용되지 않은 변수의 별표는 전역 확장에서 특별한 의미를 갖습니다. 그들은 동일합니다:
$ v='sec*et' ; ls $v
'sec*et' 'sec\*et' 'sec\et' secet secret 'sec\ xxx et'
$ ls sec*et
'sec*et' 'sec\*et' 'sec\et' secet secret 'sec\ xxx et'
*
(B) 백슬래시 이후에는 별표가 특별한 의미를 잃습니다.
$ ls sec\*et
'sec*et'
(C) 리터럴 백슬래시로 인해 별표가 *
특별한 의미를 잃을 수는 없습니다.
$ v='sec\\*et' ; ls $v
'sec\*et' 'sec\et' 'sec\ xxx et'
$ ls sec\\*et
'sec\*et' 'sec\et' 'sec\ xxx et'
내가 이해하지 못하는 것은 다음과 같습니다.
그런데 이상한 점은,별표는 특별한 의미를 잃지만 백슬래시는 삭제되지 않습니다., 이 경우:
$ v='sec\*et' ; ls $v
'sec\*et'
어떻게 보면 문자 그대로의 백슬래시 뒤에 문자 그대로의 별표가 오는 것과 같습니다.
$ ls sec\\\*et
'sec\*et'
그런데 왜? 고려하다:
따옴표 안의 특수 문자가 리터럴이 되면 (A)는 유지되지 않습니다.
별표 뒤에 백슬래시가 오기 때문에 리터럴이 되는 경우
sec*et
(B)에서처럼 백슬래시를 삭제하고 file 과 일치시키지 않는 이유는 무엇입니까?
애플리케이션에서 Bracket Expression을 사용하는 것 외에 [*]
glob 확장에 사용될 때 리터럴 별표와 일치하는 문자열 변수를 어떻게 정의할 수 있습니까?
$ v='sec < what what what > et' ; ls $v
'sec*et'
답변1
$ v="sec\*et"
$ v='sec\*et'
둘 중 하나는 변수를 로 설정하며 sec\*et
, 변수가 값을 가져오는 방식은 와일드카드의 동작에 영향을 주지 않습니다.
sec\*et
Bash가 인용되지 않은 후속 확장을 처리하는 방식은 이스케이프 처리되지 않은 glob 문자가 없기 때문에 문자열이 glob으로 처리되지 않는 것 같습니다.별말씀을요. 예를 들어 트리거되지 않으며 failglob
백슬래시가 제거되지 않습니다. 대신, 있는 그대로 인쇄합니다. (이것은 그 자체로 패턴 일치가 아닙니다. 해당 이름의 파일이 없더라도 문자열을 반환합니다.)
sec[*]et
이는 다음과 관련이 있습니다.예공.
또한 이를 사용한다면 sec\*et*
glob이 되며 다음으로 시작하는 파일 이름과 일치합니다 sec*et
(즉, 백슬래시 제거).
내가 아는 한 대부분의 Bash 버전은 이런 방식으로 작동합니다. 예외는 Bash 5.0입니다. 이는 sec\*et
glob으로 처리되어 예를 들어 Failglob을 트리거합니다.
$ ./bash-4.4/bash -c 'shopt -s failglob; v="sec\*et"; echo $v'
sec\*et
$ ./bash-5.0/bash -c 'shopt -s failglob; v="sec\*et"; echo $v'
./bash-5.0/bash: no match: sec\*et
$ ./bash-5.1.16/bash -c 'shopt -s failglob; v="sec\*et"; echo $v'
sec\*et
$ ./bash-5.2.15/bash -c 'shopt -s failglob; v="sec\*et"; echo $v'
sec\*et
(모든 경우에 모든 쉘 버전을 테스트하지는 않았습니다.)