LEARN X · ЗА 14 МИН

Tcl

Tcl за 14 минут: весь язык на одной странице через закомментированный код. Команды, переменные, строки, списки, expr, циклы, proc, массивы, regexp.

Tcl (Tool Command Language) — минималистичный скриптовый язык, где всё является командой, а всё значение — строка. Синтаксис умещается в горстку правил подстановки. Ниже — почти весь язык на одной странице: читай комментарии в коде.

Вывод и комментарии

Программа на Tcl — это последовательность команд. Команда — это первое слово строки, остальное — её аргументы.

# Это комментарий. Он работает ТОЛЬКО там, где Tcl ждёт начало команды.

# puts — команда вывода. Слова после неё — аргументы.
puts "Привет, мир!"

# Каждая строка — отдельная команда. "Всё команда":
# даже if, for, set, proc — это обычные команды, а не ключевые слова.
puts {Фигурные скобки тоже задают строку, но без подстановок}

# Точка с запятой разделяет команды в одной строке
puts "один"; puts "два"

# Комментарий в конце строки требует ; перед #
puts "hi" ;# вот теперь это комментарий

Переменные

Команда set создаёт и изменяет переменные. Знак $ подставляет значение переменной.

# set ИМЯ ЗНАЧЕНИЕ — присваивание
set name "Аня"
set age 25

# $ВАР — подстановка значения переменной
puts "Имя: $name, возраст: $age"

# set с одним аргументом ЧИТАЕТ значение
puts [set name]      ;# то же, что $name

# Подстановка $ внутри двойных кавычек работает,
# внутри фигурных скобок — НЕТ (буквальный текст)
puts "value: $age"   ;# value: 25
puts {value: $age}   ;# value: $age

# unset удаляет переменную
unset age

# ${имя} — явные границы имени переменной
set x 5
puts "${x}0"         ;# 50

Строки

В Tcl всё — строка. Число, список, имя — всё это текст. Семейство команд string работает со строками.

set s "Hello, Tcl"

# Длина, индексация, срез
puts [string length $s]          ;# 10
puts [string index $s 0]         ;# H
puts [string range $s 0 4]       ;# Hello

# Регистр
puts [string toupper $s]         ;# HELLO, TCL
puts [string tolower $s]         ;# hello, tcl

# Поиск и замена подстроки
puts [string first "Tcl" $s]     ;# 7 (индекс вхождения)
puts [string map {Tcl Мир} $s]   ;# Hello, Мир

# Проверки
puts [string match "Hel*" $s]    ;# 1 (glob-шаблон)
puts [string equal $s "Hello"]   ;# 0

# Конкатенация и format
set full "$s!!!"
puts [format "%-10s|%05d" abc 42]  ;# abc       |00042

# {} vs "": кавычки делают подстановку, скобки — нет
set n 3
puts "n=$n"   ;# n=3
puts {n=$n}   ;# n=$n

Числа и выражения

Сами по себе числа — это строки. Арифметику считает команда expr.

# expr вычисляет математическое выражение
puts [expr {2 + 3 * 4}]          ;# 14
puts [expr {10 / 3}]             ;# 3  (целочисленное)
puts [expr {10.0 / 3}]           ;# 3.333...
puts [expr {10 % 3}]             ;# 1  (остаток)
puts [expr {2 ** 10}]            ;# 1024 (степень)

# Скобки {} вокруг выражения — хороший тон:
# они откладывают подстановку, expr сам разбирает $переменные
set a 5
set b 2
puts [expr {$a > $b}]            ;# 1 (истина)
puts [expr {$a == 5 && $b < 3}] ;# 1

# Математические функции
puts [expr {sqrt(16)}]           ;# 4.0
puts [expr {max(3, 7, 2)}]       ;# 7
puts [expr {int(3.9)}]           ;# 3

# Результат можно сохранить
set sum [expr {$a + $b}]
puts $sum                        ;# 7

Списки

Список — это строка из слов, разделённых пробелами. Команды list, lindex, lappend и др. работают с ними безопасно.

# Создание списка
set fruits [list apple banana cherry]
set nums {1 2 3 4 5}             ;# фигурные скобки — тоже список

# Длина и доступ по индексу (с нуля)
puts [llength $fruits]           ;# 3
puts [lindex $fruits 0]          ;# apple
puts [lindex $fruits end]        ;# cherry

# Добавление элемента (меняет переменную)
lappend fruits date
puts $fruits                     ;# apple banana cherry date

# Срез, поиск, вставка
puts [lrange $nums 1 3]          ;# 2 3 4
puts [lsearch $fruits banana]    ;# 1 (индекс)
puts [linsert $nums 0 0]         ;# 0 1 2 3 4

# Сортировка и объединение
puts [lsort $fruits]             ;# apple banana cherry date
puts [lsort -integer {3 1 2}]    ;# 1 2 3
puts [join $nums "+"]            ;# 1+2+3+4+5
puts [split "a,b,c" ","]         ;# a b c

# Перебор списка
foreach f $fruits {
    puts "фрукт: $f"
}

# foreach сразу по двум переменным
foreach {k v} {имя Аня город Москва} {
    puts "$k = $v"
}

Условия

if, elseif, else — это команды. Условие лучше брать в фигурные скобки (его вычислит expr).

set score 75

# Классический if/elseif/else
if {$score >= 90} {
    puts "отлично"
} elseif {$score >= 60} {
    puts "хорошо"
} else {
    puts "плохо"
}

# Слово then необязательно. Скобки { } обязательны для тел.
if {$score > 0} {
    puts "положительно"
}

# switch — выбор по значению
set cmd "start"
switch $cmd {
    start   { puts "запуск" }
    stop    { puts "остановка" }
    default { puts "неизвестно" }
}

# switch с шаблонами glob и -- (конец опций)
switch -glob -- "file.txt" {
    *.txt { puts "текст" }
    *.jpg { puts "картинка" }
}

Циклы

Три основных цикла: for, foreach и while. Тело и условие — в фигурных скобках.

# for {инициализация} {условие} {шаг} {тело}
for {set i 0} {$i < 5} {incr i} {
    puts "i = $i"
}

# incr увеличивает переменную (по умолчанию на 1)
set c 10
incr c        ;# 11
incr c 5      ;# 16
incr c -1     ;# 15

# while {условие} {тело}
set n 3
while {$n > 0} {
    puts "осталось $n"
    incr n -1
}

# foreach — самый частый цикл по коллекции
foreach color {красный зелёный синий} {
    puts $color
}

# break и continue работают как обычно
for {set i 0} {$i < 10} {incr i} {
    if {$i == 3} continue
    if {$i == 6} break
    puts $i
}

Процедуры

Команда proc создаёт новую команду. Аргументы могут иметь значения по умолчанию и собираться в args.

# proc ИМЯ {аргументы} {тело}
proc greet {name} {
    return "Привет, $name!"
}
puts [greet "Аня"]               ;# Привет, Аня!

# Значение аргумента по умолчанию
proc power {base {exp 2}} {
    return [expr {$base ** $exp}]
}
puts [power 5]                   ;# 25
puts [power 2 10]                ;# 1024

# args собирает переменное число аргументов в список
proc sum {args} {
    set total 0
    foreach n $args {
        set total [expr {$total + $n}]
    }
    return $total
}
puts [sum 1 2 3 4 5]             ;# 15

# Без return процедура возвращает результат последней команды
proc double {x} { expr {$x * 2} }
puts [double 21]                 ;# 42

# Переменные внутри proc локальны.
# global даёт доступ к глобальной переменной.
set counter 0
proc tick {} {
    global counter
    incr counter
}
tick; tick
puts $counter                    ;# 2

Массивы

Массивы в Tcl — это ассоциативные (хеш-таблицы) с ключами-строками. Доступ — через имя(ключ).

# Запись по ключу
set person(name) "Аня"
set person(age)  25
set person(city) "Москва"

# Чтение
puts $person(name)               ;# Аня
puts "$person(name), $person(age) лет"

# array — команды для работы с массивом целиком
puts [array size person]         ;# 3
puts [array names person]        ;# city name age (порядок любой)
puts [array exists person]       ;# 1

# Перебор массива
foreach key [array names person] {
    puts "$key => $person($key)"
}

# Массив из списка пар ключ-значение
array set colors {red FF0000 green 00FF00 blue 0000FF}
puts $colors(green)              ;# 00FF00

# array get превращает массив обратно в список пар
puts [array get colors]

# Удаление элемента
unset person(city)

Подстановка команд

Квадратные скобки [...] выполняют команду и подставляют её результат на это место — ядро композиции в Tcl.

# [команда] выполняется, результат вставляется вместо скобок
set now [clock seconds]
puts "timestamp: $now"

# Вложенность любой глубины
puts [string length [lindex {aa bbb cccc} 2]]   ;# 4

# Результат команды — аргумент другой команды
set x [expr {[llength {1 2 3}] * 10}]
puts $x                          ;# 30

# Внутри " " подстановка [ ] тоже работает
set name "мир"
puts "Длина слова: [string length $name]"  ;# Длина слова: 3

# Внутри { } — НЕ работает (буквальный текст)
puts {Тут [команда] не выполнится}

Регулярные выражения

regexp ищет совпадение, regsub заменяет. Шаблон удобно брать в фигурные скобки.

# regexp ШАБЛОН СТРОКА — вернёт 1, если совпадение есть
puts [regexp {[0-9]+} "abc123"]      ;# 1
puts [regexp {^\d+$} "abc"]          ;# 0

# Захват подвыражений в переменные
set date "2026-06-16"
if {[regexp {(\d+)-(\d+)-(\d+)} $date -> y m d]} {
    puts "год=$y месяц=$m день=$d"
}

# -all -inline вернёт список всех совпадений
puts [regexp -all -inline {\d+} "a1 b22 c333"]  ;# 1 22 333

# regsub ШАБЛОН СТРОКА ЗАМЕНА — замена
puts [regsub {\s+} "a   b" "_"]      ;# a_b (первое вхождение)
puts [regsub -all {\d} "a1b2c3" "#"] ;# a#b#c#

# Обратные ссылки \1 в замене
puts [regsub {(\w+)@(\w+)} "user@host" {\2.\1}]  ;# host.user

Особенности языка

Главные идеи, которые отличают Tcl от привычных языков.

# 1. ВСЁ — СТРОКА. Число 42, список {1 2 3}, имя — это текст.
set n 42
puts [string length $n]          ;# 2 — да, у числа есть "длина"

# 2. ВСЁ — КОМАНДА. if, for, proc, set — обычные команды.
#    Поэтому скобки { } у тел обязательны: это аргументы команды.

# 3. ФИГУРНЫЕ СКОБКИ ОТКЛАДЫВАЮТ ПОДСТАНОВКУ.
#    " " — подстановка $ и [ ] происходит сразу.
#    { } — текст передаётся буквально, без подстановки.
set x 10
puts "сейчас: $x"                 ;# сейчас: 10
puts {потом: $x}                  ;# потом: $x

# Именно поэтому условия пишут в { }: чтобы expr/if сами
# решили, КОГДА подставлять переменные.
if {$x > 5} { puts "да" }         ;# правильно
# if "$x > 5" ... — подставит сразу, медленнее и опаснее

# 4. Подстановка \ для спецсимволов
puts "строка1\nстрока2\tтаб"

# 5. Команды можно переименовывать и создавать на лету
rename puts say
say "puts теперь зовётся say"
Поддержать проект