使Tcl/Expect语句更少”;贪婪的;
考虑下面的Expect脚本。它创建一个测试文件,每行(a、b、c、a、b、c)上都有一个字符,并使用spawn打开该文件:使Tcl/Expect语句更少”;贪婪的;,tcl,expect,Tcl,Expect,考虑下面的Expect脚本。它创建一个测试文件,每行(a、b、c、a、b、c)上都有一个字符,并使用spawn打开该文件: #!/usr/bin/expect -f proc create_test_file {fname} { set chan [open $fname w] puts $chan "a\nb\nc" puts $chan "a\nb\nc" catch {close $chan} } log_user 0 create_test_file
#!/usr/bin/expect -f
proc create_test_file {fname} {
set chan [open $fname w]
puts $chan "a\nb\nc"
puts $chan "a\nb\nc"
catch {close $chan}
}
log_user 0
create_test_file "test_file.txt"
set f [open "test_file.txt" r]
spawn -open $f
while {1} {
expect {
"c" { send_user "C\n" }
"b" { send_user "B\n" }
"a" { send_user "A\n" }
eof { break }
}
}
输出为:
C
C
输出是预期的,因为expect不会逐行处理文件,而是
而是一下子。expect语句“c”中的第一行将丢弃带有a和b的第一行,然后将第三行与c匹配,以此类推,用于下一个循环
其他expect语句也会匹配这些行,但它们从来没有机会这样做,因为第一条语句匹配第一条语句,即使第一条语句丢弃了更多的行
我想我理解这种行为,但现在我的问题是:有没有办法调整expect的行为,使匹配的expect语句是需要丢弃文件中最少行数的语句?因此,生产的产量将如下所示:
A
B
C
A
B
C
默认情况下,模式是未编排的。您可以使用
^
将它们作为正则表达式锚定到缓冲区的开头。例如,要逐个字符进行匹配,请跳过带有regexp
的未匹配字符:
while {1} {
expect {
-re "^c" { send_user "C\n" }
-re "^b" { send_user "B\n" }
-re "^a" { send_user "A\n" }
-re "^." { exp_continue }
eof { break }
}
}
尽管我在上面使用了正则表达式,但在这种情况下没有必要这样做,因为默认的“glob”模式也接受
^
来表示缓冲区的开始,因此您也可以使用
"^c" { send_user "C\n" }
"^b" { send_user "B\n" }
"^a" { send_user "A\n" }
"^?" { exp_continue }
其中
?
匹配glob模式中的单个字符,相当于regexp中的
。默认情况下,模式是未编排的。您可以使用^
将它们作为正则表达式锚定到缓冲区的开头。例如,要逐个字符进行匹配,请跳过带有regexp
的未匹配字符:
while {1} {
expect {
-re "^c" { send_user "C\n" }
-re "^b" { send_user "B\n" }
-re "^a" { send_user "A\n" }
-re "^." { exp_continue }
eof { break }
}
}
尽管我在上面使用了正则表达式,但在这种情况下没有必要这样做,因为默认的“glob”模式也接受
^
来表示缓冲区的开始,因此您也可以使用
"^c" { send_user "C\n" }
"^b" { send_user "B\n" }
"^a" { send_user "A\n" }
"^?" { exp_continue }
其中
?
匹配全局模式中的单个字符,相当于regexp中的
。有不同的方法来执行您描述的操作,但您的实际用例是什么?注意,您的put
应该是put$chan
。是的,这是正确的。我在复制时出错。有不同的方法来执行您描述的操作,但您真正的用例是什么?请注意,您的put
应该是put$chan
。是的,这是正确的。我复制时出错了。太好了,可以了,谢谢!起初我不理解“^”的必要性,但后来我意识到它与新行匹配。此外,exp_continue在此处是可选的,因为存在外部循环。>^匹配expect已读取的缓冲区的开头,而不是任何特定字符。是的,我理解,但在您上面的回答中,如果省略了:-re“^.”{exp_continue}行,脚本将只打印一次,因为字符之间没有与换行符匹配的内容(A\nb\nc\na\nb\nc\n)。这就是我说它符合新行的意思。你是对的,我把“^.”
误读为“^”
!很抱歉,我会删除那条评论,稍后再删除这条。太好了,很有效,谢谢!起初我不理解“^”的必要性,但后来我意识到它与新行匹配。此外,exp_continue在此处是可选的,因为存在外部循环。>^匹配expect已读取的缓冲区的开头,而不是任何特定字符。是的,我理解,但在您上面的回答中,如果省略了:-re“^.”{exp_continue}行,脚本将只打印一次,因为字符之间没有与换行符匹配的内容(A\nb\nc\na\nb\nc\n)。这就是我说它符合新行的意思。你是对的,我把“^.”
误读为“^”
!很抱歉,我将删除该评论,稍后再删除此评论。