Tcl 从文件中读取显示的行

Tcl 从文件中读取显示的行,tcl,Tcl,我正在读取一个文件,需要找到准确的行$(eval$(call CreateTest KEYWORD)以及该行后面的所有内容(因为其余内容都是随机的)。这就是我目前试图找到它的方式,但它总是报告没有找到匹配的内容 proc listFromFile {$path1} { set find {$(eval $(call CreateTest, KEYWORD} upvar path1 path1 set f [open $path1 r] set data [spli

我正在读取一个文件,需要找到准确的行
$(eval$(call CreateTest KEYWORD
)以及该行后面的所有内容(因为其余内容都是随机的)。这就是我目前试图找到它的方式,但它总是报告没有找到匹配的内容

proc listFromFile {$path1} {
    set find {$(eval $(call CreateTest, KEYWORD}
    upvar path1 path1
    set f [open $path1 r]
    set data [split [string trim [read $f]] \n]
    close $f
#   return [lsearch -all -inline $data *KEYWORD*]
    return [lsearch -exact -all -inline $data $find*]
}
注释掉的行是我能让它工作的最接近的行,但它会在文件中的任何地方提取任何带有关键字的内容。关键字可能出现在我不想阅读的行中,因此我需要如上所述提取准确的行

编辑 我应该提到文件的格式是这样的

$(eval $(call CreateTest, KEYWORD ...
$(eval $(call CreateTest, NOT_KEYWORD ...
$(eval $(call CreateTest, KEYWORD ...
$(eval $(call CreateTest, KEYWORD ...
$(eval $(call CreateTest, NOT_KEYWORD ...
$(eval $(call CreateTest, KEYWORD ...
这意味着我只想提取包含确切字符串和关键字的行。但在我要查找的内容之间,有几行我不想显示,而是使用:

# foo.tcl
set f [open "data.txt" r]
set body [read $f]

puts -nonewline [string range $body [string first "ccc" $body] [string length $body]]

close $f
测试:

使用,而不是:

# foo.tcl
set f [open "data.txt" r]
set body [read $f]

puts -nonewline [string range $body [string first "ccc" $body] [string length $body]]

close $f
测试:


我认为你应该在读每一行的时候把你的匹配应用到每一行

proc getMatchingLines {filename match} {
    set result {}
    set f [open $filename r]
    while {[gets $f line] != -1} {
        if {[string match ${find}* $line]} {
            lappend result $line
        }
     }
    close $f
    return $result
}

set find {$(eval $(call CreateTest, KEYWORD}
set matching [getMatchingLines $filename $find]
foreach line $matching {
    # do something with the matching line
}

您可以建立一个结果列表,或者根据应用程序的需要立即为每个匹配行执行某些操作。主要区别在于
字符串匹配
不像regexp那样有很多元字符。只有
*
是特殊的,因此匹配字符串后的行非常简单你可以做任何事情,比如:
${find}*

我认为你应该在阅读每一行的时候将你的匹配应用到每一行

proc getMatchingLines {filename match} {
    set result {}
    set f [open $filename r]
    while {[gets $f line] != -1} {
        if {[string match ${find}* $line]} {
            lappend result $line
        }
     }
    close $f
    return $result
}

set find {$(eval $(call CreateTest, KEYWORD}
set matching [getMatchingLines $filename $find]
foreach line $matching {
    # do something with the matching line
}

您可以建立一个结果列表,或者根据应用程序的需要立即为每个匹配行执行某些操作。主要区别在于
字符串匹配
不像regexp那样有很多元字符。只有
*
是特殊的,因此匹配字符串后的行非常简单我想在你的代码中,你使用了
*
作为全局模式

return [lsearch -exact -all -inline $data $find*]
当使用
-exact
标志时,它会将该
*
视为一个文本
*
,因此无法获得所需的结果。删除该
*
将解决问题

proc listFromFile {$path1} {
    set find {$(eval $(call CreateTest, KEYWORD }
    upvar path1 path1
    set f [open $path1 r]
    set data [split [string trim [read $f]] \n]
    close $f
    return [lsearch -all -inline $data $find]]
}

我认为您在代码中使用了
*
作为全局模式

return [lsearch -exact -all -inline $data $find*]
当使用
-exact
标志时,它会将该
*
视为一个文本
*
,因此无法获得所需的结果。删除该
*
将解决问题

proc listFromFile {$path1} {
    set find {$(eval $(call CreateTest, KEYWORD }
    upvar path1 path1
    set f [open $path1 r]
    set data [split [string trim [read $f]] \n]
    close $f
    return [lsearch -all -inline $data $find]]
}
这应该起作用:

proc listFromFile path {
    set f [open $path r]
    set data [split [string trim [read $f]] \n]
    close $f
    return [lsearch -exact -all -inline $data { KEYWORD}]
}
在我对您先前问题的回答中,我建议将
lsearch
(不带
-exact
)和
关键字*
作为一种模式,因为这似乎是您所追求的。考虑到您在此处显示的行,搜索后跟字符串
关键字的空格字符似乎更可行

另一件事:您的参数问题(您试图用
upvar
解决)是参数名附加了一个美元符号。如果您省略了美元符号,您会得到一个可用的参数名,如上面的代码所示(即使与美元符号一起使用也可能,但难度要大得多)

文档:,,,

这应该可以:

proc listFromFile path {
    set f [open $path r]
    set data [split [string trim [read $f]] \n]
    close $f
    return [lsearch -exact -all -inline $data { KEYWORD}]
}
在我对您先前问题的回答中,我建议将
lsearch
(不带
-exact
)和
关键字*
作为一种模式,因为这似乎是您所追求的。考虑到您在此处显示的行,搜索后跟字符串
关键字的空格字符似乎更可行

另一件事:您的参数问题(您试图用
upvar
解决)是参数名附加了一个美元符号。如果您省略了美元符号,您会得到一个可用的参数名,如上面的代码所示(即使与美元符号一起使用也可能,但难度要大得多)


文档:,,,,

很抱歉,我应该更具体地说明我要找的内容。请参阅编辑。这对我来说是一个好的开始,谢谢!很抱歉,我应该更具体地说明我要找的内容。请参阅编辑。这对我来说是一个好的开始,谢谢!没有找到任何结果。我已经尝试过,但当我运行它,它没有找到任何东西,但是如果我使用
return[lsearch-all-inline-not$data$find]]
它会显示整个文件…可能是因为内容可能因空格不同而有所不同。您必须注意。如果您注意到,我使用了带有尾随空格的find变量,因为在我的输入文件中,我的内容带有空格。您可以尝试修剪它们。这对我来说很有效。这没有找到任何结果。我我已经试过了,但是当我运行它时,它没有找到任何东西,除非我使用
return[lsearch-all-inline-not$data$find]]
它会显示整个文件…可能是内容可能因空格不同而有所不同。您必须注意。如果您注意到,我使用了带有尾随空格的find变量,因为在我的输入文件中,我的内容带有空格。您可以尝试修剪它们。这对我来说很有效。您有什么方法将其用于
return
?我问这个问题的唯一原因是因为我以后调用它的方式需要它,这完全取决于你想要返回的内容。我已经修改了它以返回所有匹配的行。我现在可以使用它,但我不完全确定它为什么可以使用。出于某种原因,添加
exec cat…
可以使用它,但是如果没有它,命令会失败。。。?你有没有办法将此与
返回一起使用
?我问这个问题的唯一原因是因为我以后调用它的方式需要它,而这取决于你想要返回什么。我已经修改了它以返回所有匹配的行。我现在可以使用它,但我不完全确定它为什么可以工作。出于某种原因,添加
exec cat…
就可以了工作,但如果没有它,命令将失败…?如果您从proc的args列表中删除
$
,您应该能够从proc主体中删除
upvar
命令。如果您删除