在tcl中将文件内容作为文件名本身

时间:2015-03-29 05:10:21

标签: tcl

我正在运行一个tcl脚本,它将文件作为" stdin"的输入。问题是它将文件内容作为文件名并在命令行处理器上运行脚本时抛出错误。

tcl脚本

#!/bin/sh
# SystemInfo_2.tcl \
exec tclsh "$0" ${1+"$@"}


set traps [read stdin];
#set traps "snmp trap test"
set timetrap [clock format [clock seconds]];

set trapout [open Database_traps_event.txt a+];
set javaout [open JavaTrapOutput.txt a+];
puts $trapout $timetrap;
puts $trapout $traps;
puts $trapout "Before executing java program";
set javaprogargs "open {|java -cp mysql-connector-java-5.1.10.jar;.  EventAlarmHandling \"$traps\"} r";
puts $trapout $javaprogargs;
set javaprogram [eval $javaprogargs];
puts $trapout "Execution of java is over"
while { [gets $javaprogram line] != -1 } {
    puts $javaout $line; 
    }
close $javaprogram;


puts $trapout "After excution of java program\r\n\r\n\r\n\r\n\r\n";
close $trapout;
close $javaout; 
exit;

输入文件内容是 -

<UNKNOWN>
UDP: [192.168.1.19]:60572->[0.0.0.0]:0
.iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.sysUpTimeInstance 1:9:58:56.61
.iso.org.dod.internet.snmpV2.snmpModules.snmpMIB.snmpMIBObjects.snmpTrap.snmpTrapOID.0 .iso.org.dod.internet.snmpV2.snmpModules.snmpMIB.snmpMIBObjects.snmpTraps.linkDown
.iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex.1 8
.iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifAdminStatus.8 up
.iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOperStatus.8 down

从命令行运行,如下所示

E:\eventAlarmHandling>tclsh TclTempFile.tcl < traps.txt
couldn't read file "UNKNOWN>
UDP: [192.168.1.19]:60572->[0.0.0.0]:0
.iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.sysUpTimeInstance 1:9:58:56.61
.iso.org.dod.internet.snmpV2.snmpModules.snmpMIB.snmpMIBObjects.snmpTrap.snmpTrapOID.0 .iso.org.dod.intern
et.snmpV2.snmpModules.snmpMIB.snmpMIBObjects.snmpTraps.linkDown
.iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex.1 8
.iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifAdminStatus.8 up
.iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifOperStatus.8 down": No error
    while executing
"open {|java -cp mysql-connector-java-5.1.10.jar;.  EventAlarmHandling "<UNKNOWN>
UDP: [192.168.1.19]:60572->[0.0.0.0]:0
.iso.org.dod.internet.mgmt.mib..."
    ("eval" body line 1)
    invoked from within
"eval $javaprogargs"
    invoked from within
"set javaprogram [eval $javaprogargs]"
    (file "TclTempFile.tcl" line 26)

在命令行中清楚地表明&#34;无法读取文件UNKNOWN&gt; ......&#34; 所以请解释一下,在命令行中发生了什么。我是tcl的新手。希望有人帮助我。

由于

1 个答案:

答案 0 :(得分:0)

您在管道如何在Tcl中工作的一个棘手问题上遇到了问题。如果我们仔细查看documentation ,我们会看到:

  

如果 fileName 的第一个字符是“|”,那么 fileName 的其余字符将被视为描述命令管道的参数列表。以与exec的参数相同的样式调用。

这意味着您必须让第一个字符为|,其余部分在剥离第一个字符后才是正确的列表。在你的情况下,你没有那个。相反,你正在做:

set javaprogargs "open {|java -cp mysql-connector-java-5.1.10.jar;.  EventAlarmHandling \"$traps\"} r";

无论如何,这非常复杂。让我们以惯用的方式构建它:

set CPsep ";"
set classpath [list mysql-connector-java-5.1.10.jar .]
set javaprogargs [list open |[list \
        java -cp [join $classpath $CPsep] EventAlarmHandling $traps]]

将类路径分开是有帮助的;它中有一个;字符(在Windows上;如果您移植到Linux或OSX,则需要更改它)并且使用list更好在Tcl中构建东西然后join转换成Java期望的东西。

我们也不再需要在那里使用任何反斜杠引用的子串(除了我用来保持线条简短和可读的那个); list命令的模式将添加所需的一切。请注意那里的|[list …]:Tcl 中到处都是非惯用的,除非在建议练习时创建管道,因为它反向执行open预期解析。


您遇到的另一件事是this

  

如果 arg (或 arg 对)具有下面描述的形式之一,则exec使用它来控制输入流并在子进程之间输出。这些参数不会传递给子进程。

     

[...]
  < fileName
  打开由 fileName 命名的文件,并将其用作管道中第一个命令的标准输入。

$traps中的论据以<开头,因此会触发此规则。

不幸的是,有 没有 的简单解决方法,这是管道创建代码的一个严重的,已知的,非常烦人的限制。处理此问题的唯一已知技术是通过文件或通过子进程的标准输入来转移数据,这两者都需要修改子进程的实现。如果您可以从System.in读取该Java程序(无论如何都是一个好主意,所以您不会触及Windows的命令行长度限制!)那么您可以传递这样的值:

set CPsep ";"
set classpath [list mysql-connector-java-5.1.10.jar .]
set javaprogargs [list open |[list \
        java -cp [join $classpath $CPsep] EventAlarmHandling << $traps]]

只需在值之前添加<<即可。