셸 문법 기초 — 셸이 내 명령을 읽는 순서, 따옴표, 주석

이 글은 GNU Bash 매뉴얼 3.1 Shell Syntax에서 다루는 내용을, 처음 배우는 분도 이해할 수 있게 쉬운 말로 풀어 정리한 글입니다. 셸이 우리가 입력한 한 줄을 ​어떤 순서로 읽고 처리하는지, 그리고 그 과정에서 가장 자주 사고가 나는 ​따옴표 와 ​주석 을 자세히 살펴봅니다.

이 글을 읽고 나면

  • 셸이 명령 한 줄을 처리하는 순서를 머릿속에 그릴 수 있습니다.

  • 큰따옴표 · 작은따옴표 · 백슬래시 · $'...'의 차이를 정확히 구분할 수 있습니다.

  • 왜 변수는 거의 항상 따옴표로 감싸야 하는지 이해합니다.

  • 주석이 언제 주석으로 인식되는지 알 수 있습니다.

셸은 한 줄을 어떻게 읽을까

우리가 터미널에 명령을 한 줄 입력하거나, 스크립트의 한 줄이 실행될 때, 셸은 그 텍스트를 ​한 번에 통째로 실행하지 않습니다. 사람처럼 순서대로 읽고 뜻을 해석합니다. 이 순서를 알면 “왜 이렇게 동작하지?” 하는 대부분의 의문이 풀립니다.

셸이 한 줄을 처리하는 흐름을 쉽게 그리면 이렇습니다.

Text

입력 한 줄 │ ▼ ① 잘게 나누기 "단어"와 "기호"로 분리 (공백 기준) │ ▼ ② 명령 형태로 묶기 무엇이 명령이고 무엇이 인자인지 구분 │ ▼ ③ 펼치기(확장) $​변수 → 값, $(명령) → 결과, *.txt → 실제 파일들 │ ▼ ④ 입출력 연결 > 파일, < 파일 같은 방향 전환 처리 │ ▼ ⑤ 실행 실제 프로그램/내장 명령 실행 │ ▼ ⑥ 결과 기다리기 끝날 때까지 기다리고, 성공/실패(종료 코드) 회수

여기서 특히 중요한 단계는 ①번(잘게 나누기) 와 ③번(펼치기) 입니다. 공백을 기준으로 단어를 나누기 때문에, ​값에 공백이 들어 있으면 의도치 않게 여러 조각으로 쪼개집니다. 바로 이 지점을 통제하는 도구가 따옴표입니다.

따옴표 — 특별한 글자의 힘을 잠재우는 장치

따옴표의 목적은 하나로 요약됩니다. ​어떤 글자가 가진 "특별한 뜻"을 없애서, 있는 그대로의 글자로 다루게 만드는 것 입니다.

예를 들어 $는 “뒤에 오는 이름을 변수 값으로 바꿔라”라는 특별한 뜻이 있고, 공백은 “여기서 단어를 나눠라”라는 특별한 뜻이 있습니다. 이 특별함을 상황에 맞게 켜고 끄는 것이 따옴표입니다.

Bash에는 따옴표(비슷한 것 포함)가 네 종류 있습니다. 하나씩 보겠습니다.

1) 큰따옴표 "..." — 변수는 펼치되, 공백은 지킨다

가장 많이 쓰는 형태입니다. 안에 있는 대부분의 글자는 그대로 두면서, $​변수$(명령) 같은 ​펼치기는 그대로 살려 둡니다. 동시에 공백이 있어도 ​한 덩어리로 유지 해 줍니다.

Bash

name="Ada Lovelace" echo "hello, $name" # → hello, Ada Lovelace

$name은 값으로 바뀌었지만, "Ada Lovelace"라는 공백 포함 값이 쪼개지지 않고 그대로 나왔습니다. 실무에서 경로·이름을 다룰 때 이 성질이 안전을 지켜 줍니다.

2) 작은따옴표 '...' — 안의 모든 글자를 글자 그대로

작은따옴표 안에서는 ​어떤 특별함도 동작하지 않습니다. $도 그냥 달러 기호일 뿐입니다.

Bash

echo 'hello, $name' # → hello, $name

변수로 바꾸고 싶지 않은 문자열, 예를 들어 정규식 패턴이나 안내 문구를 그대로 보여줄 때 좋습니다.

3) 백슬래시 \ — 바로 뒤 한 글자만 평범하게

백슬래시는 ​바로 뒤에 오는 한 글자 의 특별함만 없앱니다. 딱 한 글자만 처리하고 싶을 때 편리합니다.

Bash

echo "price is \$100" # → price is $100 ($ 를 글자로) echo "she said \"hi\"" # → she said "hi" (큰따옴표 안에 큰따옴표)

또, 줄 끝에 백슬래시를 두면 “아직 명령이 안 끝났다”는 뜻이 되어 ​다음 줄로 이어서 쓸 수 있습니다. 긴 명령을 여러 줄로 나눠 읽기 좋게 만들 때 씁니다.

Bash

echo "this is one" \ "single command" # → this is one single command

4) $'...' — 줄바꿈·탭 같은 특수 문자를 실제로 넣기

작은따옴표는 모든 것을 글자 그대로 두기 때문에, 줄바꿈(\n)이나 탭(\t)을 넣을 수 없습니다. 이럴 때 앞에 $를 붙인 $'...'를 쓰면, \n·\t 같은 표기를 ​실제 줄바꿈·탭으로 바꿔 줍니다.

Bash

printf '%b\n' $'line1\nline2\ttabbed' # line1 # line2 tabbed

자주 쓰는 표기를 정리하면 다음과 같습니다.

표기

실제 의미

\n

줄바꿈

\t

\r

캐리지 리턴

\\

백슬래시 한 개

\'

작은따옴표

방식

$​변수 펼침?

공백 유지?

주 용도

"..." (큰따옴표)

O

O

값을 넣으면서 안전하게 (가장 많이 씀)

'...' (작은따옴표)

X

O

글자 그대로 보존

\ (백슬래시)

뒤 한 글자만

특수문자 하나만 평범하게

$'...'

X (대신 \n 등 해석)

O

줄바꿈·탭 등 특수문자 삽입

왜 변수는 항상 따옴표로 감싸야 할까

앞에서 본 “잘게 나누기” 단계 때문입니다. 따옴표 없이 변수를 쓰면, 값 안의 공백에서 ​단어가 쪼개져 인자 개수가 달라집니다.

Bash

name="Ada Lovelace" count_args() { echo "argc=$#"; } # $# 은 받은 인자 개수 count_args $name # → argc=2 ("Ada" 와 "Lovelace" 로 쪼개짐) count_args "$name" # → argc=1 ("Ada Lovelace" 한 덩어리)

파일 경로에 공백이 있으면 이 차이가 곧바로 버그가 됩니다. 예를 들어 rm $pathpath에 공백이 있으면 ​여러 파일을 지우려 시도 할 수 있습니다. 그래서 규칙은 간단합니다.

주석 — # 뒤는 무시된다

#으로 시작하는 단어부터 그 ​줄 끝까지 는 주석으로 처리되어 실행되지 않습니다. 단, #이 주석이 되려면 줄의 시작이거나, 앞에 공백이 있어야 합니다.

Bash

# 이 줄 전체는 설명입니다. echo "hello" # 이 부분도 주석입니다. echo "value#1" # 주석 아님! 앞에 공백이 없어 그냥 글자입니다.

세 번째 줄에서 value#1#은 앞에 공백이 없어 ​주석이 아니라 문자열의 일부로 취급됩니다. 이 미묘한 규칙 때문에 “주석이 안 먹는다” 하는 경우가 가끔 생깁니다. 주석을 붙일 때는 앞에 공백을 한 칸 두는 습관이 안전합니다.

실행 예제

아래 스크립트는 지금까지 설명한 따옴표의 차이를 한 화면에서 직접 비교해 보여 줍니다. 같은 $name이라도 어떤 따옴표로 감쌌는지에 따라 ​값으로 바뀌기도 하고, 글자 그대로 남기도 하며, 두 조각으로 쪼개지기도 합니다.

Bash

#!/usr/bin/env bash # 따옴표 종류에 따라 셸이 텍스트를 어떻게 다르게 읽는지 보여줍니다. set -eu # 이 줄 전체는 주석입니다. '#' 뒤는 그 줄 끝까지 무시됩니다. name="Ada Lovelace" # (1) 값에 공백이 있어도 따옴표로 묶으면 한 덩어리 echo "=== 1) 큰따옴표: 변수는 펼치고, 공백은 지킨다 ===" echo "hello, $name" # (2) 큰따옴표 → $name 이 값으로 바뀜 echo echo "=== 2) 작은따옴표: 안의 모든 글자를 글자 그대로 ===" echo 'hello, $name' # (3) 작은따옴표 → $name 이 글자 그대로 출력 echo echo "=== 3) 이스케이프(\\): 바로 뒤 한 글자의 특별함을 없앤다 ===" echo "price is \$100" # (4) \$ → $ 를 글자로 취급 echo "she said \"hi\"" # (5) \" → 큰따옴표 안에서 큰따옴표 쓰기 echo echo "=== 4) 따옴표 없는 변수는 공백에서 쪼개진다 (단어 분리) ===" count_args() { echo "argc=$#"; } # (6) 받은 인자 개수($#)를 출력하는 작은 함수 count_args $name # (7) 따옴표 없음 → "Ada" "Lovelace" 두 개로 쪼개짐 (argc=2) count_args "$name" # (8) 따옴표 있음 → "Ada Lovelace" 한 개 (argc=1) echo echo "=== 5) ANSI-C 따옴표 \$'...': 특수 문자를 실제 문자로 ===" printf '%b\n' $'line1\nline2\ttabbed' # (9) \n=줄바꿈, \t=탭으로 해석 echo echo "=== 6) 줄 끝 백슬래시: 한 명령을 여러 줄로 ===" echo "this is one" \ # (10) 줄 끝 \ → 다음 줄과 이어진 한 명령 "single command" echo echo "ok — 같은 텍스트라도 따옴표가 의미를 바꿉니다."

​주요 라인별 설명
1: 공백이 있는 값을 큰따옴표로 묶어 한 변수에 담습니다.
2–3: 같은 $name이라도 큰따옴표는 값으로 펼치고, 작은따옴표는 $name을 글자 그대로 둡니다.
4–5: \$"의 특별함을 잠시 끕니다.
6–8: 따옴표 유무에 따라 인자가 2개로 쪼개지거나 1개로 유지됩니다. 실무에서 가장 자주 나는 실수입니다.
9: $'...'\n, \t를 실제 줄바꿈·탭으로 넣습니다.
10: 줄 끝 백슬래시로 긴 명령을 여러 줄에 나눠 씁니다.

실행하면 대략 이런 결과가 나옵니다.

Text

=== 1) 큰따옴표: 변수는 펼치고, 공백은 지킨다 === hello, Ada Lovelace === 2) 작은따옴표: 안의 모든 글자를 글자 그대로 === hello, $name === 3) 이스케이프(\): 바로 뒤 한 글자의 특별함을 없앤다 === price is $100 she said "hi" === 4) 따옴표 없는 변수는 공백에서 쪼개진다 (단어 분리) === argc=2 argc=1 === 5) ANSI-C 따옴표 $'...': 특수 문자를 실제 문자로 === line1 line2 tabbed === 6) 줄 끝 백슬래시: 한 명령을 여러 줄로 === this is one single command

헷갈리기 쉬운 부분

  1. ​큰따옴표와 작은따옴표를 반대로 사용 — 변수를 값으로 바꾸고 싶은데 작은따옴표로 감싸면 $name이 그대로 출력됩니다. “값이 안 들어간다” 싶으면 따옴표 종류부터 확인하세요.

  2. ​따옴표를 아예 빼먹기 — 당장은 잘 되는 것처럼 보여도, 값에 공백이나 * 같은 글자가 들어오는 순간 조용히 깨집니다. 습관적으로 "$var".

  3. #이 주석이 안 됨 — 바로 앞에 공백이 없으면 주석으로 인식되지 않습니다. echo hi# comment가 아니라 echo hi # comment.

  4. ​작은따옴표 안에 작은따옴표 — 넣을 수 없습니다. 'it'\''s' 방식으로 우회하거나, 큰따옴표를 쓰세요.

한 줄 요약

**​셸은 한 줄을 “나누고 → 펼치고 → 실행”하며, 그 과정에서 특수 문자의 힘을 켜고 끄는 도구가 따옴표입니다. 값은 큰따옴표로, 글자 그대로는 작은따옴표로, 주석은 # 앞에 공백을 두고 입력합니다.

On this page