TCL:通过SHELL环境变量检查文件存在性(另一个)

TCL:通过SHELL环境变量检查文件存在性(另一个),tcl,Tcl,我有一个文件,其中包含文件路径的行。有时路径包含SHELL环境变量,我想检查文件是否存在。 以下是我的解决方案: set fh [open "the_file_contain_path" "r"] while {![eof $fh]} { set line [gets $fh] if {[regexp -- {\$\S+} $line]} { catch {exec /usr/local/bin/tcsh -c "echo $line" } line if {!

我有一个文件,其中包含文件路径的行。有时路径包含SHELL环境变量,我想检查文件是否存在。 以下是我的解决方案:

set fh [open "the_file_contain_path" "r"]

while {![eof $fh]} { 
  set line [gets $fh]
  if {[regexp -- {\$\S+} $line]} {
    catch {exec /usr/local/bin/tcsh -c "echo  $line" } line
      if {![file exists $line]} {
        puts "ERROR: the file $line is not exists"
      }
  }
}
我相信有更优雅的解决方案,而不使用


/usr/local/bin/tcsh-c

TCL程序可以使用内置的全局变量
env
读取环境变量。阅读该行,查找
$
,后跟名称,查找
$::env($name)
,然后用它替换变量


如果文件是由不受信任的用户提供的,那么使用shell进行此操作是非常糟糕的。如果他们把
;文件中的rm*
?如果要使用shell,至少应该使用sh或bash,而不是tcsh。

TCL程序可以使用内置全局变量
env
读取环境变量。阅读该行,查找
$
,后跟名称,查找
$::env($name)
,然后用它替换变量


如果文件是由不受信任的用户提供的,那么使用shell进行此操作是非常糟糕的。如果他们把
;文件中的rm*
?如果要使用shell,至少应该使用sh或bash,而不是tcsh。

您可以在regexp命令中捕获变量名,并在Tcl的global
env
数组中进行查找。此外,将
eof
用作while条件意味着您的循环将重复一次(请参阅)


您可以在regexp命令中捕获变量名,并在Tcl的global
env
数组中进行查找。此外,将
eof
用作while条件意味着您的循环将重复一次(请参阅)


首先,在
while
循环中使用
get
eof
而不是
get
时,通常更容易(对于小文件,比如不超过1–2MB的文件)读取整个文件并将其拆分为行。(split命令的速度非常快。)

其次,要进行替换,需要在字符串中找到要替换的位置,因此使用
regexp-index
。这确实意味着您需要采取更复杂的方法来进行替换,使用
string range
string replace
来完成部分工作。假设您使用的是Tcl 8.5

set fh [open "the_file_contain_path" "r"]

foreach line [split [read $fh] "\n"] {
    # Find a replacement while there are any to do
    while {[regexp -indices {\$(\w+)} $line matchRange nameRange]} {

        # Get what to replace with (without any errors, just like tcsh)
        set replacement {}
        catch {set replacement $::env([string range $line {*}$nameRange])}

        # Do the replacement
        set line [string replace $line {*}$matchRange $replacement]
    }

    # Your test on the result
    if {![file exists $line]} {
        puts "ERROR: the file $line is not exists"
    }
}

首先,在
while
循环中使用
get
eof
而不是
get
时,通常更容易(对于小文件,比如不超过1–2MB的文件)读取整个文件并将其拆分为行。(split命令的速度非常快。)

其次,要进行替换,需要在字符串中找到要替换的位置,因此使用
regexp-index
。这确实意味着您需要采取更复杂的方法来进行替换,使用
string range
string replace
来完成部分工作。假设您使用的是Tcl 8.5

set fh [open "the_file_contain_path" "r"]

foreach line [split [read $fh] "\n"] {
    # Find a replacement while there are any to do
    while {[regexp -indices {\$(\w+)} $line matchRange nameRange]} {

        # Get what to replace with (without any errors, just like tcsh)
        set replacement {}
        catch {set replacement $::env([string range $line {*}$nameRange])}

        # Do the replacement
        set line [string replace $line {*}$matchRange $replacement]
    }

    # Your test on the result
    if {![file exists $line]} {
        puts "ERROR: the file $line is not exists"
    }
}

这不完全是一回事;它不能很好地处理
$FOO/bar
。您好,Glenn,您更新的解决方案工作正常。非常感谢。那不是一回事;它不能很好地处理
$FOO/bar
。您好,Glenn,您更新的解决方案工作正常。谢谢。