输入&输出
在本章中,我们将使用 Tcl 中的输入和输出操作。 Tcl 有几个执行 io 的命令。 我们将介绍其中的一些。
Tcl 使用称为通道的对象读取和写入数据。 可以使用open
或socket
命令创建通道。 Tcl 脚本可使用三个标准通道,而无需显式创建它们。 操作系统会为每个新应用自动打开它们。 它们是stdin
,stdout
和stderr
。 脚本使用标准输入stdin
来读取数据。 脚本使用标准输出stdout
写入数据。 脚本使用标准错误stderr
来编写错误消息。
在第一个示例中,我们将使用puts
命令。 它具有以下概要:
puts ?-nonewline? ?channelId? string
channelId
是我们要在其中写入文本的通道。 channelId
是可选的。 如果未指定,则采用默认值stdout
。
#!/usr/bin/tclsh
puts "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.tcl
Message 1
Message 2
Message 3
示例输出。
read
命令
read
命令用于从通道读取数据。 可选参数指定要读取的字符数。 如果省略,该命令将从通道读取所有数据,直到最后。
#!/usr/bin/tclsh
set 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/tclsh
puts -nonewline "Enter your name: "
flush stdout
set name [gets stdin]
puts "Hello $name"
该脚本要求用户输入,然后打印一条消息。
puts -nonewline "Enter your name: "
puts
命令用于将消息打印到终端。 -nonewline
选项禁止换行符。
flush stdout
Tcl 缓冲区在内部输出,因此用puts
编写的字符可能不会立即出现在输出文件或设备上。 flush
命令强制输出立即显示。
set name [gets stdin]
gets
命令从通道读取一条线。
$ ./hello.tcl
Enter your name: Jan
Hello Jan
脚本的示例输出。
pwd
和cd
命令
Tcl 具有pwd
和cd
命令,类似于 shell 命令。 pwd
命令返回当前工作目录,cd
命令用于更改工作目录。
#!/usr/bin/tclsh
set dir [pwd]
puts $dir
cd ..
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/tclsh
set files [glob *.tcl]
foreach file $files {
puts $file
}
该脚本将所有带有.tcl
扩展名的文件打印到控制台。
set files [glob *.tcl]
glob
命令返回与*.tcl
模式匹配的文件列表。
foreach file $files {
puts $file
}
我们浏览文件列表,并将列表的每个项目打印到控制台。
$ ./globcmd.tcl
attributes.tcl
allfiles.tcl
printing.tcl
hello.tcl
read.tcl
files.tcl
globcmd.tcl
write2file.tcl
cwd.tcl
readfile.tcl
isfile.tcl
addnumbers.tcl
这是globcmd.tcl
脚本的示例输出。
处理文件
file
命令操纵文件名和属性。 它有很多选择。
#!/usr/bin/tclsh
puts [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/tclsh
set 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/tclsh
set fp [open days w]
set days {Monday Tuesday Wednesday Thursday Friday Saturday Sunday}
puts $fp $days
close $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 days
Monday Tuesday Wednesday Thursday Friday Saturday Sunday
我们运行脚本并检查days
文件的内容。
在下面的脚本中,我们将从文件中读取数据。
$ cat languages
Python
Tcl
Visual Basic
Perl
Java
C
C#
Ruby
Scheme
我们在目录中有一个简单的文件,称为语言。
#!/usr/bin/tclsh
set fp [open languages r]
set data [read $fp]
puts -nonewline $data
close $fp
我们从提供的文件中读取数据,读取其内容,然后将数据打印到终端。
set fp [open languages r]
我们通过以只读模式打开语言文件来创建频道。
set data [read $fp]
如果我们没有为read
命令提供第二个参数,它将从文件中读取所有数据,直到文件结尾。
puts -nonewline $data
我们将数据打印到控制台。
$ ./readfile.tcl
Python
Tcl
Visual Basic
Perl
Java
C
C#
Ruby
Scheme
readfile.tcl
脚本的示例运行。
eof
命令检查所提供通道的行尾。
#!/usr/bin/tclsh
set fp [open languages]
while {![eof $fp]} {
puts [gets $fp]
}
close $fp
我们使用eof
命令读取文件的内容。
while {![eof $fp]} {
puts [gets $fp]
}
循环继续进行,直到eof
遇到文件结尾都返回true
为止。 在体内,我们使用gets
命令从文件中读取一行。
$ ./readfile2.tcl
Python
Tcl
Visual Basic
Perl
Java
C
C#
Ruby
Scheme
readfile2.tcl
脚本的示例运行。
下一个脚本将执行一些其他文件操作。
#!/usr/bin/tclsh
set fp [open newfile w]
puts $fp "this is new file"
flush $fp
file copy newfile newfile2
file delete newfile
close $fp
我们打开一个文件,并在其中写入一些文本。 文件被复制。 然后删除原始文件。
file copy newfile newfile2
file copy
命令复制文件。
file delete newfile
原始文件用file delete
命令删除。
在最后一个示例中,我们将使用文件属性。
#!/usr/bin/tclsh
set files [glob *]
set mx 0
foreach 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.tcl
Name Size
attributes.tcl 337 bytes
newfile2 17 bytes
allfiles.tcl 75 bytes
printing.tcl 83 bytes
languages 51 bytes
hello.tcl 109 bytes
days 57 bytes
read.tcl 113 bytes
files.tcl 140 bytes
globcmd.tcl 82 bytes
write2file.tcl 134 bytes
doc 4096 bytes
cwd.tcl 76 bytes
tmp 4096 bytes
readfile.tcl 98 bytes
isfile.tcl 219 bytes
样品运行。
在本章中,我们介绍了 Tcl 中的输入/输出操作。