if문이 끝나도 변수는 남습니다
Bash의 if는 조건에 따라 명령을 실행합니다. 그 자체로 새 변수 범위나 새 프로세스를 만들지는 않습니다. 조건문 안에서 값을 바꾸면 같은 셸의 변수가 바뀝니다.
value=before
if true; then
value=after
fi
printf '%s\n' "$value"출력은 after입니다. true가 성공하므로 대입문을 실행하고, fi를 지난 뒤에도 그 값을 읽습니다. 반대로 조건이 거짓이면 대입문을 실행하지 않아 기존 값이 유지됩니다.
- 조건문 직전value = before
- 조건이 참이면 대입같은 변수의 값을 after로 바꿉니다.
- 조건문 다음 명령value = after를 읽습니다.
위에서 아래로 실행 순서를 나타냅니다. 세 상자 모두 같은 셸의 상태입니다.
값이 분리되는 경계를 확인합니다
| 형태 | 변경이 남는 곳 |
|---|---|
if …; then …; fi, { …; } | 같은 셸입니다. 묶었다는 이유만으로 변수 범위가 생기지 않습니다. |
| 함수의 일반 대입 | 기본적으로 호출한 셸의 변수를 바꿉니다. 함수 안에서 local을 사용하면 지역 변수를 만들 수 있습니다. |
( … ) | 서브셸 환경에서 바뀝니다. 바깥 셸의 값은 유지됩니다. |
bash child.sh | 새 Bash에서 바뀝니다. 종료할 때 부모 변수에 자동으로 반영되지 않습니다. |
source ./child.sh | 현재 Bash에서 파일을 읽어 실행합니다. 변수와 작업 디렉터리 변경도 현재 셸에 남습니다. |
value=parent
( value=child; printf 'inside=%s\n' "$value" )
printf 'outside=%s\n' "$value"출력은 inside=child, outside=parent입니다. 괄호 안의 대입이 부모의 변수 저장 공간을 고치는 것은 아닙니다. 함수의 local은 C의 중괄호 범위와도 다릅니다. Bash는 동적 범위를 사용하므로 호출된 함수가 호출자의 지역 변수를 볼 수 있습니다.
export는 이후 실행할 프로그램에 값을 전달합니다
NOTE_VALUE=parent
export NOTE_VALUE
bash -c 'printf "child=%s\n" "$NOTE_VALUE"; NOTE_VALUE=changed'
printf 'parent=%s\n' "$NOTE_VALUE"| 명령 | 무엇이 바뀌나요? |
|---|---|
NOTE_VALUE=parent | 현재 셸에 문자열 값을 저장합니다. |
export NOTE_VALUE | 이 변수를 이후 실행하는 명령의 환경에 포함하도록 표시합니다. |
bash -c … | 자식은 전달받은 parent를 출력한 뒤 자신의 값을 changed로 바꿉니다. |
마지막 printf | 부모는 여전히 parent를 출력합니다. |
이미 실행 중인 다른 프로세스에 값이 퍼지는 것은 아닙니다. 셸이 종료되면 그 셸의 변수는 없어지지만, 먼저 실행되어 값을 상속받은 자식의 환경까지 지워지지는 않습니다.
env -i command는 그 명령에 빈 환경을 전달하며 부모 셸의 변수를 삭제하지 않습니다. 설정 파일에서 export 줄을 지운 뒤 source해도 이미 저장된 값은 자동으로 없어지지 않습니다. 현재 셸에서 제거하려면 해당 변수의 unset 여부를 따로 정해야 합니다. set과 env 역시 각각 셸 상태와 명령의 환경을 보여 주는 것이며 시스템의 모든 프로세스 변수를 한꺼번에 조회하는 명령은 아닙니다.
${value}와 $(command)는 다른 문법입니다
value='hello world'
printf '%s\n' "${value}"
result=$(printf '%s\n' 'hello world')
printf '%s\n' "$result"${value}는 변수 값을 꺼내고, $(…)는 안의 명령을 실행한 표준 출력을 가져옵니다. 따라서 $(value)는 value라는 명령을 실행하려는 표현입니다. 명령 치환은 끝부분의 개행을 제거합니다.
값을 다른 명령의 인자로 넘길 때 "$value"처럼 큰따옴표로 감싸면 공백 분리와 파일 이름 확장을 막을 수 있습니다. 대입문의 = 양옆에는 공백을 넣지 않습니다.