다음 스크립트:
$ cat runme01.sh
#!/bin/bash
A=myval
B=$A/{fix}
C=$A/fix
set -xT
echo $B
echo $C
실행하면 다음이 인쇄됩니다.
$ ./runme01.sh
+ echo 'myval/{fix}'
myval/{fix}
+ echo myval/fix
myval/fix
보시다시피 변수는 B
작은따옴표로 전달되고 변수는 작은따옴표 없이 전달됩니다.echo
C
아마도 교정기 때문에 그런 것 같습니다.
나는 항상 따옴표 없이 전달하고 싶습니다. 어떻게 하나요?
답변1
추적 출력을 순전히 정보 제공용으로 해석하지 마십시오. 이것은 디버그 출력입니다.
myval/{fix}
작은 따옴표 안의 중괄호는 쉘이 특정 문자열을 다른 것으로 해석하는 것 외에는 별 의미가 없다는 것을 보여줍니다 .특히, 그렇습니다아니요문자열이 인용되었다는 뜻입니다! 중괄호가 다음과 같기 때문에 쉘은 추적 출력에 작은따옴표를 추가합니다.때때로그러나 이 경우에는 특별하지 않습니다(실제 버팀대 확장을 사용하지 않기 때문에).
여기서도 같은 일이 발생합니다(빈 디렉터리에서 실행).
$ echo *
+ echo '*'
*
내 명령에 인용문을 사용하지 않으므로 *
쉘이노력하다그것을 연장하기 위해. 아무것도 확장되지 않으므로 확장되지 않은 상태로 유지됩니다. 추적 출력을 생성하는 코드는 *
문자열의 a를 확인하고 이를 인용합니다.이는 인쇄되는 문자열에 있는 문자를 기반으로 작은따옴표를 기계적으로 추가하는 것을 기반으로 하며 명령이나 결과에 어떤 방식으로든 영향을 주지 않습니다.
이를 다시 설명하면 다음과 같습니다.
$ ls -l
total 0
-rw-r--r-- 1 kk wheel 0 Jun 14 20:15 "filename"
-rw-r--r-- 1 kk wheel 0 Jun 14 20:13 'filename'
-rw-r--r-- 1 kk wheel 0 Jun 14 20:14 *
-rw-r--r-- 1 kk wheel 0 Jun 14 20:14 **
-rw-r--r-- 1 kk wheel 0 Jun 14 20:14 123
-rw-r--r-- 1 kk wheel 0 Jun 14 20:14 file
-rw-r--r-- 1 kk wheel 0 Jun 14 20:14 long name
-rw-r--r-- 1 kk wheel 0 Jun 14 20:14 {}
$ echo *
+ echo '"filename"' ''\''filename'\''' '*' '**' 123 file 'long name' '{}'
"filename" 'filename' * ** 123 file long name {}
즉, 문자열의 특정 문자로 인해 추적 출력을 생성하는 코드가 실패하게 됩니다 bash
. 또한 쉘은 문자열에서 작은따옴표를 이스케이프합니다.
이것을 또는 다음과 dash
비교하십시오 pdksh
.
$ echo *
+ echo "filename" 'filename' * ** 123 file long name {}
"filename" 'filename' * ** 123 file long name {}
이러한 특정 쉘은 따옴표를 추가하지 않습니다(또는 작은 따옴표를 이스케이프 처리합니다). 실제로는 중요하지 않습니다. 단지 디버그 출력일 뿐입니다.
쉘이 문자열에 대해 토큰화 및 파일 이름 생성(globbing)을 수행하도록 명시적으로 원하지 않는 한 항상 큰따옴표로 묶인 변수 확장을 사용하십시오.
큰따옴표가 항상 그런 것은 아닙니다.필요, 그러나 불필요한 문맥을 기억하는 것보다 항상 큰따옴표를 사용하는 것을 기억하는 것이 더 쉽습니다.
스크립트가 수정되었습니다:
#!/bin/bash
A=myval
B="$A/{fix}"
C="$A/fix"
set -xT
printf '%s\n' "$B"
printf '%s\n' "$C"
이렇게 하면 값에 관계없이 항상 이러한 값을 가져와서 $B
표준 출력으로 인쇄할 수 있습니다. $C
원래 코드에서 $A
was 를 *
사용 $B
하고 $C
따옴표를 사용하지 않으면 일치하는 파일 이름을 가져올 수 있습니다.
추적 출력에서는 여전히 myval/{fix}
이 코드를 사용하여 문자열을 인용합니다. 걱정하지 마세요. 이것은 아무 의미도 없습니다. 단지 디버그 출력을 돕기 위한 셸일 뿐입니다.
관련된:
답변2
일단 설정하면 IFS=$'\n'
단어 분리가 발생하지 않으며 따옴표 없이 모든 작업을 수행할 수 있습니다.
보안 위험이 있을 수 있지만 내가 아는 한 그것은 API용이므로 어쨌든 bash 스크립트를 사용하지 않을 것입니다.
어떤 사람들은 x나 y에서는 작동하지 않는다고 말하지만 작동합니다.