Tcl의 문법은 상당히 단순하고, 커맨드의 인자를 스페이스(공백)로 단락을 짓고 나열하는 정도입니다.
command arg1 arg2 arg3 ...
한 행에 여러 개의 커맨드를 나열할 때는, 세미콜론( ; )으로 구분을 짓습니다.
command arg1 arg2 arg3 ... ; command arg1 arg2 arg3 ...
한 행이 길어질 때는, 행 끝에 백슬래쉬(\)를 두는 것으로 계속 이어 쓸 수 있습니다.
command arg1 \
arg2 arg3 ...
다음의 간단한 예제를 보겠습니다.
Hello World
Hello World를 표시하는 스크립트입니다. puts 커맨드는 문자를 표시하는 커맨드입니다. 두 개의 예제는 같은 결과를 나타냅니다.
puts stdout {Hello World}
=>Hello World
puts stderr {Hello World}
=>Hello World
puts {Hello World}
=>Hello World
puts stdout "Hello World"
=>Hello World
puts stderr "Hello World"
=>Hello World
puts "Hello World"
=>Hello World
변수
Tcl의 변수에는 타입이 없습니다. 타입을 의식하지 않고 문자열이나 정수를 변수에 대입할 수 있습니다. set 커맨드는, 변수에 값을 대입합니다. set 커맨드로 값을 생략하고, 변수명의 처음에 $을 붙여주면 값을 참조할 수 있습니다. unset 커맨드는, 변수를 메모리에서 삭제합니다.
set var 123
=>123
set var
=>123
set var abc
=>abc
puts stdout $var
=>abc
unset var
산술연산
expr 커맨드는, 정수나 부동소수점의 연산이나 비교를 행합니다. 삼각 함수나 난수등도 사용할 수 있습니다.
expr 1 / 0
=>divide by zero
expr 10 + 0x10 + 010
=>34
expr 2.0 * asin(1.0)
=>3.14159265359
set i 1
=>1
incr i
=>2
커맨드의 치환
대괄호[]는, 대괄호내의 커맨드를 커맨드의 출력결과로 치환해 줍니다.
set pi [expr 2.0 * asin(1.0)]
=>3.14159265359
set pi
=>3.14159265359
더블 쿼테이션(Double Quotation Mark)과 중괄호
더블 쿼테이션과 중괄호는, 여러 개의 문자열을 하나의 덩어리로 묶어줍니다. 단 더블 쿼테이션 내에서 변수와 커맨드는 치환이 되지만, 중괄호 내에서는 치환이 되지 않습니다. 백슬래쉬(\) 사용한다면 ‘[’과 ‘$’의 치환기능을 무효화시킬 수 있습니다.
set var 123
=>123
puts "result = $var"
=>result = 123
puts {result = $var}
=>result = $var
puts "result = \$var"
=>result = $var
set var 123
=>123
puts "result = [pwd]"
=>result = C:/
puts {result = [pwd]}
=>result = [pwd]
puts "result = \[var]"
=>result = [var]
포맷(format)
scan과 format 커맨드는 ANSI C언어의 scan과 printf함수와 서식이 같습니다. %의 서식에 의하여 문자열을 포맷합니다.
scan "123.456" "%d.%d" a b
=>2
set a
=>123
set b
=456
format "%d.%d" $a $b
=>123.456
프로시져(Procedure)
proc 커맨드는, 0개 이상의 인자를 받는 프로시져를 정의할 수 있습니다. 프로시져 안에서 정의된 변수는, 프로시져 안에서만 참조할 수 있습니다. 프로시져 밖에서 변수를 참조하고 싶다면, 변수가 선언된 프로시져와 참조할 프로시져 안에서 global로 변수를 선언하면 됩니다. 프로시져는 디폴트로 인자나, 가변인자를 받는 것도 가능합니다.
# 보통의 인자
set foo 3
=>3
proc add {a b} {
global foo
return [expr $a + $b + $foo]
}
add 1 2
=>6
# 참조형 인자와 디폴트 인자
proc plus {a {b 1}} {
upvar $a r
set r [expr $r + $b]
return $r
}
set foo 1
=>1
plus foo
=>2
plus foo 2
=>4
# 가변 인자
proc sum {args} {
set s 0
foreach i $args {
set s [expr $s + $i]
}
return $s
}
sum 1 2
=>3
sum 1 2 3
=> 6
주석(comment)
#로 시작하는 행은 주석의 행을 의미합니다. 스크립트 기술 도중 주석을 기술 시에는 ;#가 돼야 합니다.
# 주석 1
# 주석 2 \
주석 2의 계속
puts {Hello World} ; #주석 3
=>Hello World
제어문
if, for, foreach, while, switch 커맨드는 제어문으로 사용하는 커맨드입니다. if, for, while의 조건식은 expr 커맨드와 같이 사용할 수 있습니다.
if, elseif, else문
set var 일
=>일
if {$var == "일"} {
puts stdout 1
}
=>1
set var 이
=>이
if {$var == "일"} {
puts stdout 1
} else {
puts stdout 2
}
=>2
set var 삼
=>삼
if {$var == "일"} {
puts stdout 1
} elseif {$var == "이"} {
puts stdout 2
} else {
puts stdout 3
}
=>3
for, foreach, while안에서는 continue, break 커맨드를 사용할 수 있습니다.
for 문
for {set i 1} {$i <= 3} {incr i} {
puts stdout $i
}
=>1
=>2
=>3
for {set i 1} {$i <= 5} {incr i} {
if {$i < 3} {
continue
}
puts stdout $i
}
=>3
=>4
=>5
for {set i 1} {$i <= 5} {incr i} {
if {$i > 3} {
break
}
puts stdout $i
}
=>1
=>2
=>3
while 문
set i 3
=>3
while {$i != 0} {
puts stdout $i
incr i -1
}
=>3
=>2
=>1
foreach 문
foreach i {A B C} {
puts stdout $i
}
=>A
=>B
=>C
foreach {i j} {A B C D E F} {
puts stdout "$i $j"
}
=> A B
=> C D
=> E F
switch 문
switch 사과 {
사과 {puts 100원}
귤나무 {puts 80원}
바나나(banana) {puts 30원}
default {puts 모름}
}
=>100원
switch 사과 {
사과
{puts 100원}
귤나무
{puts 80원}
바나나
{puts 30원}
default
{puts 모름}
}
=>100원
after 문
after커맨드는, 커맨드의 실행시간을 지연시키는 일을 합니다. after로 지정한 커맨드는 global scope에서 실행된다는 것을 주의해야 합니다.
after 1000 ;# 1초 기다리다가..
after 1000 "set a 1" ;# 1초후에 커맨드를 실행
=>after#0
catch 문
catch 커맨드는, 에러를 캐치(catch)하는 데 사용됩니다. 에러가 발생하면 1을 리턴 시켜주고, 아니면 0을 리턴 시켜줍니다.
catch {expr 1+2} var
=>0
catch {expr 1*_} var
=>1
catch {expr 1/0} var
=>1
catch {error bug} var
=>1
에러처리
에러처리의 기술이 없다면, 에러발생 시에 아래와 같은 창이 나타납니다.
에러처리는 잊지 말고 꼭 처리해주어야 합니다.
proc foo1 {} {
return -code error -errorcode 1 -errorinfo info message
}
proc foo2 {} {
error message info 1
}
if [catch foo1] {
puts "errorCode = $errorCode"
puts "errorInfo = $errorInfo"
}
if [catch foo2] {
puts "errorCode = $errorCode"
puts "errorInfo = $errorInfo"
}
배열
배열의 첨자에 문자열을 사용할 수 있습니다. parray커맨드는, 배열의 요소를 표시합니다.
set ary(사과) 100원
=>100원
set ary(귤나무) 80원
=>80원
set ary(바나나) 30원
=>30원
parray ary
=>ary(사과) = 100원
=>ary(귤나무) = 80원
=>ary(바나나) = 30원
puts $ary(사과)
=>100원
array set ary {
사과 100원
귤나무 80원
바나나 30원
}
parray ary
=>ary(사과) = 100원
=>ary(귤나무) = 80원
=>ary(바나나) = 30원
puts $ary(사과)
=>100원
리스트
lisp와 비슷한 리스트가 준비되어 있습니다.
set list { 사과 귤나무 바나나 }
=>사과 귤나무 바나나
lappend list 멜론
=>사과 귤나무 바나나 멜론
lindex $list 2
=>바나나
lsort $list
=>귤나무 사과 바나나 멜론
문자열
문자나 문자열을 위한 커맨드가 준비되어 있습니다.
if ![string compare -nocase "abc" "ABC"] {
puts 같다
}
=>같다
string toupper "abc"
=>ABC
string length "xyz"
=>3
string length "귤나무"
=>3
split usr/local/bin /
=>usr local bin
join {usr local bin} /
=>usr/local/bin /
set str abc
=>abc
append str xyz
=>abcxyz
바이너리
물론 바이너리 문자도 지원합니다.
# ASCII to Binary
set bin [binary format i 0x12345678]
# Binary to ASCII
binary scan $bin H2H2H2H2 var1 var2 var3 var4
puts 0x$var4$var3$var2$var1
=>0x12345678
스크립트의 인자
스크립트 파일의 인자는, argc와 argv 변수로 알아낼 수 있습니다.
set 스크립트이름 $argv0
set 인자의수 $argc
set 제1인자 [lindex $argv 0]
set 제2인자 [lindex $argv 1]
set 제3인자 [lindex $argv 2]