따옴표로 셸 변수를 묶는 경우
셸 스크립트에서 변수를 따옴표로 묶어야 합니까?아니면 안 됩니까?
예를 들어, 는 다음과 같습니다.
xdg-open $URL
[ $? -eq 2 ]
또는
xdg-open "$URL"
[ "$?" -eq "2" ]
만약 그렇다면, 왜?
일반 규칙: 공백 또는 공백(또는 실제로 공백) 또는 특수 문자(와일드 카드)를 포함할 수 있는 경우 따옴표로 묶습니다.공백이 있는 문자열을 따옴표로 묶지 않으면 종종 하나의 인수가 여러 개의 인수로 분할됩니다.
$?숫자 값이기 때문에 따옴표는 필요 없습니다.★★의 유무$URL필요한 것은 무엇을 허용하느냐에 따라 달라집니다.또, 그것이 비어 있는 경우에도 논쟁을 계속하고 싶은지 아닌지에 따라 다릅니다.
그게 더 안전하기 때문에 항상 습관적으로 현을 인용하는 경향이 있어요.
즉, 단어 분할 및 와일드카드 확장을 수행하기 위해 셸이 필요하지 않은 모든 항목을 인용합니다.
작은 따옴표는 그 사이의 텍스트를 말 그대로 보호합니다.셸이 문자열에 전혀 닿지 않도록 해야 할 때 적절한 도구입니다.일반적으로 변수 보간이 필요하지 않을 때 선택하는 견적 메커니즘입니다.
$ echo 'Nothing \t in here $will change'
Nothing \t in here $will change
$ grep -F '@&$*!!' file /dev/null
file:I can't get this @&$*!! quoting right.
큰따옴표는 변수 보간이 필요한 경우에 적합합니다.적절한 적응을 실시하면, 스트링에 작은 따옴표가 필요한 경우에도 좋은 회피책이 됩니다(작은 따옴표 안에 이스케이프 메커니즘이 없기 때문에 작은 따옴표 사이에 작은 따옴표를 피할 수 있는 간단한 방법은 없습니다.따옴표 안에 이스케이프 메커니즘이 있는 경우 완전한 따옴표는 없습니다).
$ echo "There is no place like '$HOME'"
There is no place like '/home/me'
단어 분할 및/또는 와일드카드 확장을 수행하도록 셸을 특별히 요구하는 경우에는 따옴표가 적절하지 않습니다.
단어 분할(일명 토큰 분할);
$ words="foo bar baz"
$ for word in $words; do
> echo "$word"
> done
foo
bar
baz
대조적으로:
$ for word in "$words"; do echo "$word"; done
foo bar baz
(루프는 따옴표로 둘러싸인 단일 문자열에 대해1회만 실행됩니다).
$ for word in '$words'; do echo "$word"; done
$words
(루프는 리터럴한 따옴표로 둘러싸인 스트링 상에서1회만 실행됩니다).
와일드카드 확장:
$ pattern='file*.txt'
$ ls $pattern
file1.txt file_other.txt
대조적으로:
$ ls "$pattern"
ls: cannot access file*.txt: No such file or directory
.file*.txt
$ ls '$pattern'
ls: cannot access $pattern: No such file or directory
.$pattern 중 하나 둘 ,)))))))!)
좀 더 구체적으로 말하면 파일 이름을 포함하는 모든 항목은 따옴표로 묶어야 합니다(파일 이름에 공백 및 기타 셸 메타 문자를 포함할 수 있기 때문입니다).하는 모든 것은 따옴표로 에는 URL과 같은 셸 되어 있기 때문입니다).? ★★★★★★★★★★★★★★★★★」&정규식을 포함하는 모든 항목은 일반적으로 따옴표로 묶어야 합니다(ditto ditto).공백이 아닌 문자 사이에 단일 공백이 아닌 중요한 공백이 포함된 경우 따옴표로 묶어야 합니다(따옴표로 묶으면 셸이 공백이 단일 공백으로 뭉쳐져 선행 또는 후행 공백이 모두 잘라집니다).
변수가 셸 메타 문자를 포함하지 않는 값만 포함할 수 있는 경우 따옴표는 임의입니다.따옴표가 '따옴표 없음', '따옴표 없음', '따옴표 없음',$?이 변수에는 1개의 숫자밖에 포함할 수 없기 때문에 기본적으로는 괜찮습니다. ★★★★★★★★★★★★★★."$?"또한, 일반적인 일관성과 정확성을 위해 권장되고 있습니다(단, 이것은 제 개인적인 권장사항이며 널리 알려진 정책은 아닙니다).
변수가 아닌 값은 기본적으로 동일한 규칙을 따르지만 따옴표가 아닌 메타 문자를 이스케이프할 수도 있습니다.예로서 이 「URL」, 「URL」입니다.&따옴표로 묶지 않는 한됩니다.
$ wget http://example.com/q&uack
[1] wget http://example.com/q
-bash: uack: command not found
(물론 이는 URL이 따옴표로 둘러싸이지 않은 변수인 경우에도 발생합니다).정적 문자열의 경우 작은 따옴표가 가장 적합합니다.단, 여기서는 따옴표나 이스케이프가 모두 작동합니다.
wget 'http://example.com/q&uack' # Single quotes preferred for a static string
wget "http://example.com/q&uack" # Double quotes work here, too (no $ or ` in the value)
wget http://example.com/q\&uack # Backslash escape
wget http://example.com/q'&'uack # Only the metacharacter really needs quoting
마지막 예시는 또 다른 유용한 개념을 제시하는데, 저는 이것을 "시소 인용"이라고 부릅니다.단일 따옴표와 이중 따옴표를 함께 사용해야 하는 경우 서로 인접하여 사용할 수 있습니다.예를 들어, 다음과 같은 따옴표가 붙은 문자열은
'$HOME '
"isn't"
' where `<3'
"' is."
는 토큰화 및 따옴표 삭제 후 1개의 긴 문자열을 형성하여 백투백으로 붙여넣을 수 있습니다.
$ echo '$HOME '"isn't"' where `<3'"' is."
$HOME isn't where `<3' is.
이것은 읽기 쉽지는 않지만, 일반적인 기술이기 때문에 알아두면 좋습니다.
참고로 스크립트는 보통 어떤 용도로도 사용할 수 없습니다.와일드카드를 확장하려면...사용하세요.
$ printf '%s\n' $pattern # not ``ls -1 $pattern''
file1.txt
file_other.txt
$ for file in $pattern; do # definitely, definitely not ``for file in $(ls $pattern)''
> printf 'Found file: %s\n' "$file"
> done
Found file: file1.txt
Found file: file_other.txt
한 것입니다).printf특히 여러 인수로 정상적으로 동작합니다. stat와일드카드 조회를 루프하는 것은 일반적인 문제이며, 자주 잘못 행해집니다.)
루프오버할 토큰 목록을 포함하는 변수나 확장하기 위한 와일드카드는 자주 볼 수 없기 때문에 "무엇을 하고 있는지 정확히 알지 못하면 모든 것을 따옴표로 묶는다"고 생략할 수 있습니다.
견적서의 일반적인 공식은 다음과 같습니다.
큰따옴표
단어 분할과 글로벌화를 억제하고 싶은 상황입니다.또한 리터럴을 정규식이 아닌 문자열로 취급하는 컨텍스트에서도 사용할 수 있습니다.
작은따옴표
보간이나 백슬래시의 특수 처리를 억제하고 싶은 문자열 리터럴에서요즉, 큰따옴표를 사용하는 것은 부적절합니다.
따옴표 없음
단어 분할이나 글로벌 문제가 없다고 확신하거나 단어 분할과 글로벌화를 원하는 경우.
예
큰따옴표
- 공백이 있는 리터럴 문자열(
"StackOverflow rocks!","Steve's Apple") - 가변 확장(
"$var","${arr[@]}") - 명령어 치환(
"$(ls)","`ls`") - globs(디렉토리 경로 또는 파일 이름 부분에 공백 포함)
"/my dir/"*) - 작은 따옴표를 보호하다)를 보호한다.
"single'quote'delimited'string") - Bash 파라미터 확장(
"${filename##*/}")
작은따옴표
- 공백이 있는 명령어 이름과 인수
- 보간이 필요한 리터럴 문자열(
'Really costs $$!','just a backslash followed by a t: \t') - 큰따옴표를 보호하다
'The "crux"') - 보간이 필요한 정규 리터럴을 억제하다
- 특수 문자와 관련된 리터럴에 셸 인용을 사용합니다(
$'\n\t') - (shell committing)를 개 보호할 )
$'{"table": "users", "where": "first_name"=\'Steve\'}')
따옴표 없음
- 변수 주변(예: 변수 주변)
$$,$?,$#의 개요) - 으로, 를 들어 '아예'와 같은
((count++)),"${arr[idx]}","${string:start:length}" - 에 inside inside inside
[[ ]]로운 표현(이 크게 수 ) - we want we want spliting where (단어 분할
for word in $words) - we want 글로빙을 원하는 곳)
for txtfile in *.txt; do ...) - 가 곳
~로$HOME)~/"some dir"아니다"~/some dir")
다음 항목도 참조하십시오.
를 많이 ."$var"하다고 한$var에는 공백이 포함되어 있지 않습니다.
사용하고 있습니다.$var" " " " 인단인인 。
lines="`cat multi-lines-text-file.txt`"
echo "$lines" ## multiple lines
echo $lines ## all spaces (including newlines) are zapped
에디터용 https://www.shellcheck.net/ 플러그인이 지시할 때마다.
언급URL : https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable
'programing' 카테고리의 다른 글
| 복사/붙여넣기 후 Excel의 자동 셀 참조 변경을 비활성화하려면 어떻게 해야 합니까? (0) | 2023.04.15 |
|---|---|
| 장고의 CharField와 TextField의 차이점은 무엇입니까? (0) | 2023.04.15 |
| Date Time(UTC) 저장과 Date Time Offset 저장 (0) | 2023.04.15 |
| WPF 체크박스바인딩 (0) | 2023.04.15 |
| 환경 cron을 시뮬레이트하는 방법은? (0) | 2023.04.15 |