【问题标题】:need help in tcl command usage for regsub在 regsub 的 tcl 命令用法方面需要帮助
【发布时间】:2013-07-26 14:51:42
【问题描述】:

我是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。这里有没有人知道如何只在列表中注册确切的单词?

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

【问题讨论】:

  • 在 [1-9] 之前使用反斜杠(产生 \[1-9\] ),否则它会将 1-9 视为要执行的命令。

标签: regex tcl


【解决方案1】:

究竟你做了什么?

当我在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_3abc_1abc_2AAA_0 中的每一个应用四次来测试您的替换?你当然可以按照自己的方式去做,但更自然的方式是这样做

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

再一次,你想用你的替代来实现什么?看起来好像您正在尝试将 stringabc 替换为空字符串,即完全删除它。将[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 中的正则表达式命令处理 strings,所以我将它们传递给字符串。

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

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]作为其中的锚点 - 如果您沿着这条路线走,请不要忘记转义方括号或使用大括号。

【讨论】:

  • 您好 Nurdglaw,感谢您调查我的疑问。实际上,您在 regsub 命令中错过了 $test ,这是它标记错误的原因。您的试用命令 % regsub -all ${test2}_[1-9] [list] test1
  • 您的 foreach 示例是替换方法之一,但它们可能无法生成我要查找的输出,因为它们会将匹配 abc_ 的任何模式替换为 null。我尝试做的是仅替换整个匹配的精确字符串 abc_ 。下面显示了我希望从之前的结果中得到的结果:test1 是一个列表 [prefix_abc_1 abc_1 abc_0 abc_6 def],llength = 5 之后:test1 是一个带有 [prefix_abc_1 def] 的列表, llength = 2 希望这会让你清楚我的问题。谢谢:)
【解决方案2】:

\m and \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,这样可能会节省一些处理器时间。

【讨论】:

  • 你解决了我的疑惑。谢谢你启发我,Potrzebie。非常感谢:)
  • 在 8.6 中:lmap element $test1 {regsub $test2 $element ""}
猜你喜欢
  • 2018-04-04
  • 1970-01-01
  • 2011-01-27
  • 2014-02-06
  • 2017-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多