Regex TCL中的负正则表达式

Regex TCL中的负正则表达式,regex,tcl,Regex,Tcl,我有一个变量text,它是一个包含或不包含“u backup”的文件名。我需要一个正则表达式,它可以选择一个文件名,其中没有“\u backup”(如果它有*\u backup.txt,则排除)。我想在TCL中实现这一点(而不是Ruby。我使用Ruby进行说明)。我有下面这样的正则表达式 text = "some_thing.txt" text =~ /\S+[^_backup]\.txt/ # => 0 #-> correct as filename does not have _

我有一个变量
text
,它是一个包含或不包含
“u backup”
的文件名。我需要一个正则表达式,它可以选择一个文件名,其中没有
“\u backup”
(如果它有
*\u 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'
之前的排除列表中给出。如何构造排除word一部分的正则表达式?

有许多聪明的方法来表示“负匹配”,但最简单、最可读的方法是从外部否定直接匹配:

if {![regexp {_backup} $text]} {
    # do something with a name that does not contain '_backup'
    set filename [file tail $text]
}
(我假设标准操作是获取
$text
中给定路径的文件名和扩展名部分)或

随着正则表达式变得越来越复杂,代码通常变得越来越难理解。如果可以通过直接匹配和
If
命令来完成任务,那么这总比神秘的正则表达式好

可以使用
字符串匹配来代替
regexp

if {![string match {*_backup*} $text]} {
    # do something with a name that does not contain '_backup'
    set filename [file tail $text]
}
如果变量
text
中有文件路径字符串列表,则应该能够过滤掉不包含字符串
\u 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]
}
或者,仍然相当于:

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]
}
文档链接:

Tcl 8.6引入了
lmap
命令。可以找到与Tcl 8.4和Tcl 8.5兼容的纯Tcl实现



(好吧,耶!对这个答案的回答使我的声誉达到了.Thx!)

你想排除带有
\u backup
的文件名,还是带有
\u backup.txt
的文件名?哪个?“排除word的一部分”是什么意思?@sawa:filenames with
\u backup