我有一个变量text
,它是一个带或不带'_backup'
的文件名。我需要一个正则表达式来选择一个没有'_backup'
的文件名(如果它有*_backup.txt
则排除)。我想在TCL(而不是Ruby)中实现这一点。我使用Ruby作为插图目的。我有正则表达式如下。
text = "some_thing.txt"
text =~ /\S+[^_backup]\.txt/
# => 0 #-> correct as filename does not have _backup
text = "some_thinp.txt"
text =~ /\S+[^_backup]\.txt/
# => nil #-> Wrong, filename does not have _backup (returns nil as last character before .txt 'p' is one among the characters given in exclude list.
上述代码的问题是排除按字符(任何字符)排序,并且失败的文件名以'p'
之前的排除列表中给出的字符'.txt'
之一结尾。如何构建排除单词部分的正则表达式?
答案 0 :(得分:4)
有很多聪明的方法来陈述“负面匹配”,但最简单和最易读的方式是从外部否定直接匹配:
if {![regexp {_backup} $text]} {
# do something with a name that does not contain '_backup'
set filename [file tail $text]
}
(我假设标准操作是获取$text
中给出的路径的文件名和扩展名部分)或
if {[regexp {_backup} $text]} {
# do something with a name that does contain '_backup'
} else {
# do something with a name that does not contain '_backup'
set filename [file tail $text]
}
由于正则表达式变得更复杂,因此代码通常难以理解。如果可以使用直接匹配和if
命令完成作业,那么总是优于神秘的正则表达式。
可以使用regexp
代替string match
:
if {![string match {*_backup*} $text]} {
# do something with a name that does not contain '_backup'
set filename [file tail $text]
}
如果变量texts
中有文件路径字符串列表,您应该能够过滤掉不包含字符串_backup
的字符串,如下所示:
set filenames [lmap text $texts {
expr {
[regexp {_backup} $text]
? [continue]
: [file tail $text]
}
}]
或等同于:
set filenames [lmap text $texts {
if {[regexp {_backup} $text]} continue
file tail $text
}]
或者仍然等同于:
set filenames {}
foreach text $texts {
if {[regexp {_backup} $text]} continue
lappend filenames [file tail $text]
}
文档链接:regexp,string,if,file,lmap,expr,continue,{{ 3}},foreach
{1}}命令是在Tcl 8.6中引入的。可以找到与Tcl 8.4和Tcl 8.5兼容的Pure-Tcl实现lappend。
(好吧,是的!对这个回答的回应使我的声誉达到了here的辉煌。谢谢!;))