在本章中,我们将使用 Tcl 中的输入和输出操作。 Tcl 有几个执行 io 的命令。 我们将介绍其中的一些。
Tcl 使用称为通道的对象读取和写入数据。 可以使用open或socket命令创建通道。 Tcl 脚本可使用三个标准通道,而无需显式创建它们。 操作系统会为每个新应用自动打开它们。 它们是stdin,stdout和stderr。 脚本使用标准输入stdin来读取数据。 脚本使用标准输出stdout写入数据。 脚本使用标准错误stderr来编写错误消息。
在第一个示例中,我们将使用puts命令。 它具有以下概要:
puts ?-nonewline? ?channelId? string
channelId是我们要在其中写入文本的通道。 channelId是可选的。 如果未指定,则采用默认值stdout。
#!/usr/bin/tclshputs "Message 1"puts stdout "Message 2"puts stderr "Message 3"
puts命令将文本写入通道。
puts "Message 1"
如果未指定channelId,则默认情况下写入stdout。
puts stdout "Message 2"
此行与上一行相同。 我们仅明确指定了channelId。
puts stderr "Message 3"
我们写入标准错误通道。 错误消息默认情况下转到终端。
$ ./printing.tclMessage 1Message 2Message 3
示例输出。
read命令
read命令用于从通道读取数据。 可选参数指定要读取的字符数。 如果省略,该命令将从通道读取所有数据,直到最后。
#!/usr/bin/tclshset c [read stdin 1]while {$c != "q"} {puts -nonewline "$c"set c [read stdin 1]}
该脚本从标准输入通道读取一个字符,然后将其写入标准输出,直到遇到q字符为止。
set c [read stdin 1]
我们从标准输入通道(stdin)读取一个字符。
while {$c != "q"} {
我们继续读取字符,直到按q为止。
gets命令
gets命令从通道读取下一行,返回行中直到(但不包括)行尾字符的所有内容。
#!/usr/bin/tclshputs -nonewline "Enter your name: "flush stdoutset name [gets stdin]puts "Hello $name"
该脚本要求用户输入,然后打印一条消息。
puts -nonewline "Enter your name: "
puts命令用于将消息打印到终端。 -nonewline选项禁止换行符。
flush stdout
Tcl 缓冲区在内部输出,因此用puts编写的字符可能不会立即出现在输出文件或设备上。 flush命令强制输出立即显示。
set name [gets stdin]
gets命令从通道读取一条线。
$ ./hello.tclEnter your name: JanHello Jan
脚本的示例输出。
pwd和cd命令
Tcl 具有pwd和cd命令,类似于 shell 命令。 pwd命令返回当前工作目录,cd命令用于更改工作目录。
#!/usr/bin/tclshset dir [pwd]puts $dircd ..set dir [pwd]puts $dir
在此脚本中,我们将打印当前工作目录。 然后,我们更改工作目录并再次打印工作目录。
set dir [pwd]
pwd命令返回当前工作目录。
cd ..
我们将工作目录更改为当前目录的父目录。 我们使用cd命令。
$ ./cwd.tcl/home/janbodnar/prog/tcl/io/home/janbodnar/prog/tcl
样本输出。
glob命令
Tcl 具有glob命令,该命令返回与模式匹配的文件的名称。
#!/usr/bin/tclshset files [glob *.tcl]foreach file $files {puts $file}
该脚本将所有带有.tcl扩展名的文件打印到控制台。
set files [glob *.tcl]
glob命令返回与*.tcl模式匹配的文件列表。
foreach file $files {puts $file}
我们浏览文件列表,并将列表的每个项目打印到控制台。
$ ./globcmd.tclattributes.tclallfiles.tclprinting.tclhello.tclread.tclfiles.tclglobcmd.tclwrite2file.tclcwd.tclreadfile.tclisfile.tcladdnumbers.tcl
这是globcmd.tcl脚本的示例输出。
处理文件
file命令操纵文件名和属性。 它有很多选择。
#!/usr/bin/tclshputs [file volumes][file mkdir new]
该脚本将打印系统的已安装卷,并创建一个新目录。
puts [file volumes]
file volumes命令返回到系统上安装的卷的绝对路径。
[file mkdir new]
file mkdir创建一个名为new的目录。
$ ./voldir.tcl/$ ls -d */doc/ new/ tmp/
在 Linux 系统上,有一个已安装的卷-根目录。 ls命令确认new目录的创建。
在下面的代码示例中,我们将检查文件名是常规文件还是目录。
#!/usr/bin/tclshset files [glob *]foreach fl $files {if {[file isfile $fl]} {puts "$fl is a file"} elseif { [file isdirectory $fl]} {puts "$fl is a directory"}}
我们遍历当前工作目录中的所有文件名,并打印它是文件还是目录。
set files [glob *]
使用glob命令,我们创建当前目录的文件和目录名称的列表。
if {[file isfile $fl]} {
如果有问题的文件名是文件,我们将执行if命令的主体。
} elseif { [file isdirectory $fl]} {
file isdirectory命令确定文件名是否为目录。 请注意,在 Unix 上,目录是文件的特例。
puts命令可用于写入文件。
#!/usr/bin/tclshset fp [open days w]set days {Monday Tuesday Wednesday Thursday Friday Saturday Sunday}puts $fp $daysclose $fp
在脚本中,我们打开一个文件进行写入。 我们将一周中的几天写入文件。
set fp [open days w]
我们打开一个名为days的文件进行写入。 open命令返回一个通道 ID。
set days {Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
该数据将被写入文件。
puts $fp $days
我们使用open命令返回的通道 ID 写入文件。
close $fp
我们关闭打开的频道。
$ ./write2file.tcl$ cat daysMonday Tuesday Wednesday Thursday Friday Saturday Sunday
我们运行脚本并检查days文件的内容。
在下面的脚本中,我们将从文件中读取数据。
$ cat languagesPythonTclVisual BasicPerlJavaCC#RubyScheme
我们在目录中有一个简单的文件,称为语言。
#!/usr/bin/tclshset fp [open languages r]set data [read $fp]puts -nonewline $dataclose $fp
我们从提供的文件中读取数据,读取其内容,然后将数据打印到终端。
set fp [open languages r]
我们通过以只读模式打开语言文件来创建频道。
set data [read $fp]
如果我们没有为read命令提供第二个参数,它将从文件中读取所有数据,直到文件结尾。
puts -nonewline $data
我们将数据打印到控制台。
$ ./readfile.tclPythonTclVisual BasicPerlJavaCC#RubyScheme
readfile.tcl脚本的示例运行。
eof命令检查所提供通道的行尾。
#!/usr/bin/tclshset fp [open languages]while {![eof $fp]} {puts [gets $fp]}close $fp
我们使用eof命令读取文件的内容。
while {![eof $fp]} {puts [gets $fp]}
循环继续进行,直到eof遇到文件结尾都返回true为止。 在体内,我们使用gets命令从文件中读取一行。
$ ./readfile2.tclPythonTclVisual BasicPerlJavaCC#RubyScheme
readfile2.tcl脚本的示例运行。
下一个脚本将执行一些其他文件操作。
#!/usr/bin/tclshset fp [open newfile w]puts $fp "this is new file"flush $fpfile copy newfile newfile2file delete newfileclose $fp
我们打开一个文件,并在其中写入一些文本。 文件被复制。 然后删除原始文件。
file copy newfile newfile2
file copy命令复制文件。
file delete newfile
原始文件用file delete命令删除。
在最后一个示例中,我们将使用文件属性。
#!/usr/bin/tclshset files [glob *]set mx 0foreach fl $files {set len [string length $fl]if { $len > $mx} {set mx $len}}set fstr "%-$mx\s %-s"puts [format $fstr Name Size]set fstr "%-$mx\s %d bytes"foreach fl $files {set size [file size $fl]puts [format $fstr $fl $size]}
该脚本将创建两列。 在第一列中,我们有文件的名称。 在第二列中,我们显示文件的大小。
foreach fl $files {set len [string length $fl]if { $len > $mx} {set mx $len}}
在此循环中,我们找出了最长的文件名。 格式化输出列时将使用此格式。
set fstr "%-$mx\s %-s"puts [format $fstr Name Size]
在这里,我们打印列的标题。 要格式化数据,我们使用format命令。
set fstr "%-$mx\s %d bytes"foreach fl $files {set size [file size $fl]puts [format $fstr $fl $size]}
我们遍历文件列表并打印每个文件名及其大小。 file size命令确定文件的大小。
$ ./attributes.tclName Sizeattributes.tcl 337 bytesnewfile2 17 bytesallfiles.tcl 75 bytesprinting.tcl 83 byteslanguages 51 byteshello.tcl 109 bytesdays 57 bytesread.tcl 113 bytesfiles.tcl 140 bytesglobcmd.tcl 82 byteswrite2file.tcl 134 bytesdoc 4096 bytescwd.tcl 76 bytestmp 4096 bytesreadfile.tcl 98 bytesisfile.tcl 219 bytes
样品运行。
在本章中,我们介绍了 Tcl 中的输入/输出操作。
