세 가지 인용 방식
'single'은 내용을 글자 그대로 보존하며 변수와 명령 치환을 확장하지 않아."double"은 변수와 명령 치환을 확장하면서도 결과를 인자 하나로 보존해.\$와\"처럼 필요한 글자는 이스케이프할 수 있어.- 따옴표가 없으면 셸이 결과를 단어로 나누고 글로브까지 확장해. 일부러 그 동작이 필요한 경우가 아니라면 피해야 해.
먼저 한 값의 인자 경계를 지켜
name="Alice Lee"
echo $name # Alice Lee (겉보기와 달리 인자 두 개)
echo "$name" # Alice Lee (인자 하나)
for f in $files; do # $files 값을 공백 기준으로 다시 나눔
for f in "$files"; do # 값 전체를 인자 하나로 전달인용하지 않은 확장은 공백과 글로브 문자 때문에 인자 경계를 바꿔. 파일명이나 사용자 입력처럼 한 값이어야 하는 변수는 "$var"로 넘겨. 여러 값을 보관하려면 공백으로 이어 붙인 문자열이 아니라 배열을 쓰고 "${arr[@]}"로 펼치는 게 맞아.
기본값
: "${PORT:=8000}" # 설정되지 않았거나 비어 있으면 할당
echo "${USER:-anon}" # 설정되지 않았거나 비어 있으면 'anon'. USER 자체는 안 바뀜
: "${REQUIRED:?must be set}" # 설정되지 않았거나 비어 있으면 오류 후 종료앞의 :는 아무 일도 하지 않는 명령: 확장의 부수 효과만 원할 때. 매개변수 확장의 전체 표는 epilogue 트랙에서 다뤄.
사용자 입력 받기
read -rp 'Name: ' name
echo "hi $name"
# -r은 백슬래시를 글자 그대로 보존
# -s는 입력을 화면에 표시하지 않음(비밀번호 등)로컬 변수와 전역 변수
bash와 zsh 함수에서는 local var=value로 함수 안의 이름을 따로 묶을 수 있어. 생략하면 호출한 쪽의 같은 변수를 덮어쓸 수 있어. 다만 local은 POSIX sh의 표준 문법이 아니므로, #!/bin/sh 스크립트라면 기대하면 안 돼.
여러 값은 배열로 경계를 보존해
name="Project Alpha"
echo $name # 단어 분리 뒤 인자 두 개
echo "$name" # 인자 한 개
for f in $files; do # 문자열 하나를 다시 분리
for f in "$files"; do # 항상 한 번만 반복인용하지 않은 확장은 공백과 글로브 문자 때문에 인자 경계를 바꿔. 파일명과 사용자 입력처럼 한 값인 변수는 "$var"로 넘겨. 여러 값은 배열에 저장하고 "${arr[@]}"로 펼쳐.
인용은 인자 설계야
셸은 텍스트를 명령과 인자 목록으로 바꿔. 따옴표는 어디까지를 인자 하나로 보낼지 정해. 디버깅할 때는 printf '<%s>\n' "$@"처럼 실제 인자 경계를 출력해.
빈 값도 의미가 있어
인용한 빈 변수는 빈 인자 하나가 되지만, 인용하지 않은 빈 변수는 사라질 수 있어. 프로그램은 ‘옵션 값이 비어 있음’과 ‘옵션 자체가 없음’을 다르게 처리할 수 있으므로 인용은 공백뿐 아니라 빈 값의 의미도 지켜 줘.