0

我是新的学习者tcl。我在使用时遇到如下问题regsub。考虑以下场景:

set test1 [list prefix_abc_3 abc_1 abc_2 AAA_0]

set test2 abc

regsub -all ${test2}_[1-9] $test1  [list] test1

我期望$test1 output is [prefix_abc_3 AAA_0]

但是regsub也删除了部分匹配的字符串,即prefix_abc_3. 这里有没有人知道如何只在列表中注册确切的单词?

我试图通过网络找到解决方案,但无法获得任何线索/提示。感谢这里有人可以帮助我。

4

2 回答 2

1

正则表达式中的\m 和 \M分别匹配单词的开头和结尾。但是你在 中没有一串单词test1,而是一个元素列表,有时会有区别,所以不要将两者混为一谈。regsub仅处理字符串,而lsearch处理列表:

set test1 [list prefix_abc_3 abc_1 abc_2 AAA_0]
set test2 abc
set test1 [lsearch -all -inline -not -regexp $test1 "^${test2}_\[1-9\]\$"]

如果模式如此简单,您可以使用该-glob选项(默认值)来代替,-regexp并且可能会节省一些处理器时间。

于 2013-07-26T12:19:47.247 回答
0

究竟执行了什么?

当我将上面的命令键入时tclsh,它会显示一个错误 -

% set test1 [list prefix_abc_3 abc_1 abc_2 AAA_0]
prefix_abc_3 abc_1 abc_2 AAA_0
% set test2 abc
abc
% regsub -all ${test2}_[1-9] [list] test1
invalid command name "1-9"

我不确定你想做什么。您首先以test1列表形式初始化。然后通过将其传递给 regsub将其视为字符串。这是完全合法的做法,但可能表明您对某事感到困惑。prefix_abc_3您是否尝试通过对、abc_1abc_2中的每一个应用四次来测试您的替换AAA_0?你当然可以按照自己的方式去做,但更自然的方式是

foreach test $test1 {
    regsub $pattern $test [list] testResult
    puts stdout $testResult
}

再说一次,你想用你的替代来实现什么?看起来好像您正试图abc用空字符串替换该字符串,即完全删除它。[list]作为空字符串传递是完全有效的,但同样可能表明列表和字符串之间存在混淆。

为了达到你想要的结果,你需要做的就是在你的模式中添加一个前导空格,传递一个空格作为替换字符串并转义方括号,即

regsub -all " ${test2}_\[-9\]" $test1 " " test1

但我怀疑这是一个虚构的例子,你真的在​​尝试做一些稍微不同的事情。

编辑

要获取仅包含与您的模式不完全匹配的列表条目的列表,我建议

proc removeExactMatches {input} {
    set result [list];       # Initialise the result list
    foreach inputElement $input {
        if {![regexp {^abc_[0-9]$} $inputElement]} {
            lappend result $inputElement
        }
    }
    return $result
}

set test1 [removeExactMatches [list prefix_abc_3 abc_1 abc_2 AAA_0]]

笔记:

i) 我根本不使用 regsub。

ii) 虽然在列表和字符串之间切换是安全和合法的,但这都需要时间,而且它掩盖了我想要做的事情,所以我尽可能避免它。您似乎有一个字符串列表,并且您想删除其中的一些,所以这就是我在建议的解决方案中使用的。Tcl 中的正则表达式命令处理字符串,所以我将它们传递给字符串。

iii) 为确保列表元素完全匹配,我将模式锚定到我使用^and匹配的字符串的开头和结尾$

iv) 为了防止解释器识别正则表达式模式中的 [1-9] 并尝试执行(不存在的)命令1-9,我将整个模式字符串括在大括号内。

v)为了更通用,我可能想将模式传递给 proc 以及输入列表(字符串),在这种情况下,我会做

proc removeExactMatches {inputPattern input} {
    .
    .
    .
    set pattern "^"
    append pattern $inputPattern
    append pattern "\$"
    .
    .
    .
        if {![regub $pattern $inputElement]} {
        .
        .
        .
}

set test1 [removeExactMatches {abc_[1-9]} {prefix_abc_3 abc_1 abc_2 AAA_0}]

以尽量减少必须转义的字符数。(实际上我可能不会使用引号作为开始和结束锚的引号proc- 它们并不是真正需要的,而且我是一个懒惰的打字员!)

查看您最初的问题,您似乎只想更改abc模式的一部分,在这种情况下,您可能只想将其传递给您proc并附加其中_[0-9]的锚点 - 不要忘记逃避如果您沿着这条路线走,请使用方括号或使用大括号。

于 2013-07-26T11:36:31.233 回答