Tcl — Tool Command Language

Tcl — Tool Command Language

Tcl(Tool Command Language)은 모든 것이 문자열로 표현되는 명령 기반 언어예요. 스크립트를 읽고, 단어로 나누고, 치환하는 일련의 규칙이 Tcl 언어 전체의 뼈대를 이뤄요. 이 문서는 그 문법과 의미를 정의하는 핵심 규칙을 정리한 개요예요.

출처: Tcl 공식 문서 - Tcl

본문

다음 규칙들이 Tcl 언어의 문법과 의미를 정의해요.

[1] Commands. Tcl 스크립트는 하나 이상의 명령을 담은 문자열이에요. 세미콜론과 줄바꿈은(아래에서 설명하는 것처럼 인용되지 않는 한) 명령 구분자예요. 닫는 대괄호는(인용되지 않는 한) 명령 치환 중 명령 종결자예요.

[2] Evaluation. 명령은 두 단계로 평가돼요. 첫째, Tcl 인터프리터가 명령을 단어로 나누고 아래에서 설명하는 치환을 수행해요. 이 치환은 모든 명령에 대해 동일한 방식으로 수행돼요. 둘째, 첫 단어로 명령을 수행할 명령 프로시저를 찾고, 명령의 모든 단어를 그 명령 프로시저에 넘겨요. 명령 프로시저는 각 단어를 정수, 변수 이름, 리스트, Tcl 스크립트 등 원하는 방식으로 자유롭게 해석할 수 있어요. 명령마다 단어를 다르게 해석해요.

[3] Words. 명령의 단어는 공백으로 구분돼요(명령 구분자인 줄바꿈은 제외).

[4] Double quotes. 단어의 첫 문자가 큰따옴표(")면 다음 큰따옴표 문자까지가 그 단어예요. 따옴표 사이에 세미콜론, 닫는 대괄호, 공백 문자가(줄바꿈 포함) 나타나면 평범한 문자로 취급돼 단어에 포함돼요. 따옴표 사이의 문자에는 아래에서 설명하는 대로 명령 치환, 변수 치환, 백슬래시 치환이 수행돼요. 큰따옴표 자체는 단어의 일부로 남지 않아요.

[5] Argument expansion. 단어가 {*}로 시작하고 그 뒤에 비공백 문자가 오면, 앞의 {*}는 제거되고 단어의 나머지는 다른 단어처럼 파싱·치환돼요. 치환 후 그 단어는 리스트로 파싱되고(명령 치환이나 변수 치환 없이, 백슬래시 치환은 리스트에서 평소처럼 수행되며 개별 내부 단어는 중괄호나 큰따옴표로 둘러쌀 수 있음), 그 단어들이 실행되고 있는 명령에 추가돼요. 예를 들어 "cmd a {*}{b [c]} d {*}{$e f {g h}}""cmd a b {[c]} d {$e} f {g h}"와 같아요.

[6] Braces. 단어의 첫 문자가 여는 중괄호({)이고 규칙 [5]가 적용되지 않으면, 그 단어는 일치하는 닫는 중괄호(})에서 끝나요. 중괄호는 단어 안에서 중첩돼요. 열린 중괄호마다 닫는 중괄호가 하나씩 더 있어야 해요(단, 백슬래시로 인용된 중괄호는 일치하는 닫는 중괄호를 찾는 데 세지 않아요). 중괄호 사이의 문자에는 아래에서 설명하는 백슬래시-줄바꿈 치환을 제외하고 치환이 수행되지 않아요. 세미콜론, 줄바꿈, 닫는 대괄호, 공백도 특별한 해석을 받지 않아요. 단어는 바깥 중괄호 사이의 문자들로 정확히 이뤄지며, 중괄호 자체는 제외돼요.

[7] Command substitution. 단어에 여는 대괄호([)가 있으면 Tcl은 명령 치환을 수행해요. 이를 위해 Tcl 인터프리터를 재귀적으로 호출해, 여는 대괄호 뒤의 문자들을 Tcl 스크립트로 처리해요. 스크립트는 여러 명령을 담을 수 있고 닫는 대괄호(])로 끝나야 해요. 스크립트의 결과(즉 마지막 명령의 결과)가 대괄호와 그 사이의 모든 문자 대신 단어에 치환돼요. 단일 단어에 명령 치환이 여러 개 있을 수 있어요. 중괄호로 둘러싸인 단어에서는 명령 치환이 수행되지 않아요.

[8] Variable substitution. 단어에 달러 기호($) 뒤에 아래 설명된 형태 중 하나가 있으면 Tcl은 변수 치환을 수행해요. 달러 기호와 그 뒤 문자들이 변수의 값으로 단어에서 교체돼요. 변수 치환은 다음 형태를 취할 수 있어요.

  • $name: name은 스칼라 변수의 이름이에요. 이름은 문자, 숫자, 밑줄, 네임스페이스 구분자(콜론 두 개 이상)인 하나 이상의 문자 시퀀스예요. 문자와 숫자는 표준 ASCII(0–9, A–Z, a–z)만 해당돼요.
  • $name(index): name은 배열 변수의 이름이고 index는 그 배열 안의 요소 이름이에요. name은 문자, 숫자, 밑줄, 네임스페이스 구분자만 담아야 하고 빈 문자열일 수도 있어요. 문자와 숫자는 표준 ASCII만 해당돼요. index의 문자에는 명령 치환, 변수 치환, 백슬래시 치환이 수행돼요.
  • ${name}: name은 스칼라 변수나 배열 요소의 이름이에요. 닫는 중괄호를 제외하고 어떤 문자든 담을 수 있어요. namearrayName(index) 형태면 배열 요소를 나타내는데, 이때 arrayName에는 여는 괄호 (이나 닫는 중괄호 } 문자가 없어야 하고 index는 닫는 중괄호를 제외한 어떤 문자 시퀀스든 될 수 있어요. name 파싱 중 추가 치환은 수행되지 않아요.

단일 단어에 변수 치환이 여러 개 있을 수 있어요. 중괄호로 둘러싸인 단어에서는 변수 치환이 수행되지 않아요. 변수는 위에 나열된 것 외의 문자 시퀀스를 담을 수도 있지만, 그 경우 다른 메커니즘(예: set 명령의 단일 인자 형태)으로 접근해야 해요.

[9] Backslash substitution. 단어에 백슬래시(\)가 나타나면 백슬래시 치환이 발생해요. 아래 설명된 경우를 제외하고는 백슬래시가 빠지고 그 다음 문자가 평범한 문자로 취급돼 단어에 포함돼요. 이를 통해 큰따옴표, 닫는 대괄호, 달러 기호 같은 문자를 특수 처리 없이 단어에 포함시킬 수 있어요. 특별히 처리되는 백슬래시 시퀀스와 그 값은 다음과 같아요.

  • \a: 경보(벨) (유니코드 U+000007).
  • \b: 백스페이스 (U+000008).
  • \f: 폼 피드 (U+00000C).
  • \n: 줄바꿈 (U+00000A).
  • \r: 캐리지 리턴 (U+00000D).
  • \t: 탭 (U+000009).
  • \v: 수직 탭 (U+00000B).
  • \<newline>whiteSpace: 백슬래시, 줄바꿈, 줄바꿈 뒤의 모든 공백과 탭을 단일 공백 문자로 교체해요. 이 시퀀스는 명령이 실제로 파싱되기 전에 별도 선행 단계에서 교체된다는 점에서 독특해요. 즉 중괄호 사이에서 나타나도 교체되고, 그 결과 공백은 중괄호나 따옴표 안에 없으면 단어 구분자로 취급돼요.
  • \\: 백슬래시(\).
  • \ooo: 숫자 ooo(한 개, 두 개, 세 개)는 삽입될 유니코드 문자의 8비트 8진수 값으로, 범위 000–377(즉 U+000000–U+0000FF)이에요. 파서는 이 범위를 넘기기 직전이나 최대 세 자리에 도달하면 멈춰요. 유니코드 문자의 상위 비트는 0이에요.
  • \xhh: 16진수 숫자 hh(한 개 또는 두 개)는 삽입될 유니코드 문자의 8비트 16진수 값이에요. 상위 비트는 0이에요(즉 문자는 U+000000–U+0000FF 범위).
  • \uhhhh: 16진수 숫자 hhhh(한 개, 두 개, 세 개, 네 개)는 삽입될 유니코드 문자의 16비트 16진수 값이에요. 상위 비트는 0이에요(즉 U+000000–U+00FFFF 범위).
  • \Uhhhhhhhh: 16진수 숫자 hhhhhhhh(한 개에서 여덟 개)는 삽입될 유니코드 문자의 21비트 16진수 값으로, 범위 U+000000–U+10FFFF이에요. 파서는 범위를 넘기기 직전이나 최대 여덟 자리에 도달하면 멈춰요. 상위 비트는 0이에요.

범위 U+010000–U+10FFFD는 미래를 위해 예약되어 있어요. 백슬래시 치환은 중괄호로 둘러싸인 단어에서는 수행되지 않아요(위에서 설명한 백슬래시-줄바꿈은 제외).

[10] Comments. Tcl이 명령의 첫 단어의 첫 문자를 기대하는 지점에 해시 문자(#)가 나타나면, 그 해시 문자와 뒤따르는 문자들은 다음 줄바꿈까지 주석으로 취급되어 무시돼요. 주석 문자는 명령의 시작 부분에 나타날 때만 의미가 있어요.

[11] Order of substitution. 각 문자는 Tcl 인터프리터가 명령의 단어를 만들 때 정확히 한 번 처리해요. 예를 들어 변수 치환이 발생하면 변수 값에 대해 추가 치환은 수행되지 않고, 값이 단어에 그대로 삽입돼요. 명령 치환이 발생하면 중첩 명령은 Tcl 인터프리터에 대한 재귀 호출이 완전히 처리해요. 재귀 호출을 하기 전에 치환을 수행하지 않고, 중첩 스크립트의 결과에 추가 치환도 수행하지 않아요. 치환은 왼쪽에서 오른쪽으로 일어나고, 각 치환은 다음 치환을 시도하기 전에 완전히 평가돼요. 그래서 set y [set x 0][incr x][incr x] 같은 시퀀스는 항상 변수 y를 값 012로 설정해요.

[12] Substitution and word boundaries. 치환은 규칙 [5]의 인자 확장을 제외하고 명령의 단어 경계에 영향을 주지 않아요. 예를 들어 변수 치환 중 변수의 전체 값은 단어에 공백이 있어도 하나의 단어의 일부가 돼요.

더 알아보기

  • string — 문자열 조작
  • subst — 명시적 치환 수행