Уроки Tcl
#26: Выполнение внешних программ |
Tcl может использоваться как средство для связи разных программ между собой. Например, как .bat файлы DOS или shell-скрипты в Unix. Так же как в .bat файлах, вы можете вызывать другие программы из Tcl. Запущенные программы называются подпроцессами.
Есть два способа создать подпроцесс из Tcl:
Вызов open аналогичен открытию файла. Если первый символ имени файла символ потока (|), то open запустит программу, прикрепив ввод и вывод к файловому указателю. Он может быть открыт для чтения, записи, или чтения/записи.
Многие операционные системы буфферизуют ввод и вывод. Это значит, что строка, которую вы посылаете командой puts может не отправиться сразу, а будет записана в буфер. Когда буфер заполнится (или будет выполнена команда flush), то будет непосредственно выведена. При обычном запуске буфер очищается после каждой команды, однако при использовании потоков между программами для повышения эффиктивности буфер накапливает большие порции информации.
Если файл открыт для чтения и записи вы должнты знать, что потоки буферизованы. Следует периодически использовать команду flush, чтобы иметь уверенность, что данные посланы подпроцессу. Выходные данные так же не будут доступны для чтения read или gets, пока буфер подпроцесса не будет заполнен.
Вызов exec аналогичен обычному запуску программы (или нескольких программ) из командной строки. Поддерживается несколько способов перенаправления вывода, или вы можете получить вывод подпроцесса как возвращаемое значение команды exec.
open |имяПрограммы ?доступ? | |
Возвращает указатель на файл. имяПрограммы должно начинаться с символа потока (|). Если имяПрограммы заключено в кавычки или фигурные скобки, то может включать аргументы для подпроцесса. | |
exec ?ключи? арг1 ?арг2? ... ?аргN? | |
Exec воспринимает арг1 как имя запускаемой программы,
а остальные аргументы - аргументы для неё. Ключи начинаются
с "-" и могут устанавливать некоторые параметры выполнения: -keepnewline - Оставляет завершающие символы начала новой строки. (обычно они удаляются) --(два минуса) - Обозначает конец ключей. Следующий аргумент будет воспринят как имя программы, даже если начинается с минуса ("-"). |
Арг1 - аргN команды exec могут быть следующими:
Есть много разнообразных команд перенаправления ввода/вывода. Вот основной набор этих команд:
| | |
Поток вывода команды, предшествующей символу потока перенаправляется на стандартный ввод следующей команды. | |
< имяФайла | |
Первая программа потока будет читать ввод не из консоли, а из фала имяФайла | |
< @ указФайла | |
Первая программа потока будет читать из указателя на файл указФайла, который действителен в Tcl программе. УказФайла - значение возвращаемое командой open ... "r". | |
<< значение | |
Первая программа потока получит значение как входной поток. | |
> имяФайла | |
Вывод последней программы потока будет перенаправлен в файл имяФайла. Предыдущее содержимое файла будет потеряно. | |
>> имяФайла | |
Вывод последней программы потока будет добавлен к содержимому файла имяФайла. | |
2> имяФайла | |
Стандартный вывод ошибок всех программ потока будет послан в файл имяФайла. Предыдущее содержимое этого файла будет потеряно. | |
2>> имяФайла | |
Стандартный вывод ошибок всех программ потока будет добавлен в файл имяФайла. | |
>@ указФайла | |
Вывод последней программы в потоке будет записан в указФайла. УказФайла - значение, возвращаемое командой open ... "w". |
Есть несколько вещей, которые нужно помнить при использовании exec и open.
Код примера демонстрирует как использовать open и exec в паре. Это не лучший способ, но рабочий. В частности, если вы передаёте большой текст, то обычно использовать exec с перенаправлением на указФайлов быстрее.
Пример начинается с записи простой программы Tcl, которая исправляет порядок символов во временном файле. Эта программа будет запущена отдельно, для проверки записи и чтения в отдельной программе.
Как только программа записана и файл закрыт, мы можем запустить Tcl скрипт. Команда:
set io [open "|$tempFileName" r]
открывает поток для чтения и записи в новую программу. Когда строка передана в программу, следует команда flush.
Когда Tcl скрипт прочитает строку из stdin (стандартный поток ввода), он исправляет порядок символов на обратный, и записывает в stdout (стандартный поток вывода), и завершает работу. Когда программа завершает - буфер очищается, и программа примера читает выходную строку из канала.
Пример с командой exec показывает другой способ работы программы. Одна лстрока ввода может быть послана другой программе одной командой Tcl.
# Создание уникального имени для файла set tempFileName "test[pid].tcl" # Открывает файл и записывает туда программу set outfl [open $tempFileName w] puts $outfl { set len [gets stdin line] if {$len < 5} {exit -1} for {set i $len} {$i >= 0} {incr i -1} { append l2 [string range $line $i $i] } puts $l2 exit 0; } # Сбрасывает данные и закрывает файл flush $outfl close $outfl # Запускает подпрограмму из текущей и # Открывает поток к программе set io [open "|tclsh $tempFileName" r+] # посылает строку новой программе # *Данные должны быть сброшены flush* puts $io "Эта строка вернётся назад." flush $io # Получает ответ set len [gets $io line] puts "До инверсии: 'Эта строка вернётся назад.'" puts "Инвертированная строка: $line" puts "Строка содержит $len символов" # Запуск программы с заданной строкой на входе set invert [exec D:/PROGRA~1/Tcl/bin/tclsh.exe $tempFileName << \ "А РОЗА УПАЛА НА ЛАПУ АЗОРА"] # Вывод результата puts "Инверсия 'А РОЗА УПАЛА НА ЛАПУ АЗОРА' это \n $invert" # Очистка file delete $tempFileName |
Горбачев "Yurez" Юрий |