【问题标题】:how to perform substring extraction and substitution in tcl如何在 tcl 中执行子字符串提取和替换
【发布时间】:2017-02-19 22:51:49
【问题描述】:

我正在尝试从 Tcl 中的字符串中提取子字符串。我编写了代码并且能够做到,但我想知道是否有其他有效的方法来做到这一点。所以确切的问题是我有一个字符串

name_ext_10a.string_10a.string.string.string

我想提取“name_ext”,然后删除“_”并将其替换为“.”;我最终希望输出为“name.ext”。我写了这样的东西:

set _File "[string replace $_File [string last "_" $_File] [string length $_File] "" ]"
set _File "[string replace $_File [string last "_" $_File] [string length $_File] "" ]"
set _File "[string replace $_File [string last "_" $_File] [string last "_" $_File] "." ]"

这给了我想要的确切输出,但我想知道在 Tcl 中是否有任何其他有效的方法可以做到这一点。

【问题讨论】:

    标签: string tcl


    【解决方案1】:

    您可以使用下划线作为分隔符拆分该文件名,然后用点连接前 2 个元素:

    % set f name_ext_10a.string_10a.string.string.string
    name_ext_10a.string_10a.string.string.string
    % set out [join [lrange [split $f _] 0 1] .]
    name.ext
    

    编辑

    所以如果“名称”可以有任意数量的下划线:

    set f "foo_bar_baz_ext_10a.string_10a.string.string.string"
    set pieces [split $f _]
    set name [join [lrange $pieces 0 end-3] _]
    set out [join [list $name [lindex $pieces end-2]] .]  ;#==> foo_bar_baz.ext
    

    但这变得越来越复杂。一个正则表达式就足够了——我假设“字符串”可以是任何非下划线字符序列。

    set string {[^_]+}
    set regex "^(.+)_($string)_10a.${string}_10a.$string.$string.$string\$"
    regexp $regex $f -> name ext
    set out "$name.$ext"    ;#==> foo_bar_baz.ext
    

    【讨论】:

    • 是的,但问题是字符串“name”本身可以有任意数量的下划线。所以没有改变的是“_ext_10a.str_10a.str.str.str”模式。所以这就是为什么我试图用空字符串替换最后两个下划线之后的字符串,这样我就会得到“name_ext”,然后用一个点更改最后一个下划线。
    【解决方案2】:

    一种提取方法是使用regsub

    regsub {^([^_]+)_([^_]+)_.*} $_File {\1.\2} _File
    

    正则表达式包含([^_]+) 组件,它匹配一系列非下划线字符,加上一个锚点和一些下划线,以及一个尾随的非捕获.*,它匹配其他所有字符(因此我们可以丢弃它)。 regsub 用两个匹配的非下划线部分的串联替换它(这是整个字符串),两者之间有一个.,并将其写回字符串来自的_File 变量。

    请注意,我将正则表达式和替换放在大括号中。这是因为它们包含 Tcl 元字符(方括号和反斜杠),我希望 Tcl 逐字传递到 regsub

    【讨论】:

    • 谢谢多纳尔,但问题是“名称”本身可以有任意数量的下划线,所以唯一不变的模式是“_ext_10a.str_10a.str.str.str”为什么我搜索第二个最后一个下划线并将之后的所有内容替换为空字符串并将“_ext”替换为“.ext”
    • @Puneet 这种细节真的很重要;正则表达式非常依赖于正确理解要匹配的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 2016-08-20
    • 1970-01-01
    • 2020-04-05
    相关资源
    最近更新 更多