如何结合使用正则表达式来匹配带或不带分隔符的字符串?

时间:2019-03-04 17:12:34

标签: regex tcl

我有类似以下字符串的字符串,这些字符串称为 Input ,需要进行处理并将其转换为name / value对,如下所示:

输入: FOO = BAR=BAZ 输出: name='FOO', value='BAR=BAZ'

输入: FOO = BAR 输出: name='FOO', value='BAR'

输入: FOO = 输出: name='FOO', value=''

输入: = BAR=BAZ 输出: name='', value='BAR:BAZ'

输入: = BAR 输出: name='', value='BAR'

输入: FOO 输出: name='FOO', value=''

请注意,分隔符为=:。没有分隔符也是可能的。

以下代码涵盖了除最后一种情况以外的所有上述情况,

regexp {^\s*(.*?)\s*[=:]\s*(.*?)\s*$} $setting -> name value

if {![info exists name]} {
    set name {}
}

if {![info exists value]} {
    set value {}
}

puts "name='$name', value='$value'"

为其返回的

输出: name='', value=''

代替

输出: name='FOO', value=''

最后一种情况可以用下面的正则表达式覆盖:

regexp {^\s*(.*?)\s*$} $setting -> name value

如何将这些正则表达式组合在一起,使一个正则表达式可以覆盖所有情况?

3 个答案:

答案 0 :(得分:2)

我不清楚您为什么坚持使用regexp执行此操作。当您的正则表达式变得太复杂时,可能是时候使用另一种方法了。假设您的字符串中不包含任何NUL字符,则可以执行以下操作:

lassign [split [regsub {\s*[:=]\s*} [string trim $setting] \0] \0] name value

字符串修剪会消除所有周围的空白。然后,将分隔符和所有周围的空白替换为NUL字符。最后,在该NUL字符上将结果分成两部分,并将这两个部分分配给名称和值变量。

根据我的测量,这种方法的速度是regexp变体的两倍以上。

答案 1 :(得分:1)

  

如何将这些正则表达式组合在一起,使一个正则表达式可以覆盖所有情况?

前者已经包括后者:)但是,更广泛的正则表达式不能匹配最后一种情况(FOO),因为它根本不包含定界符。观看[regexp]的结果,该结果将为0

请考虑以下内容:

 ^\s*([^=:]*)\s*[=:]?\s*(.*)\s*$

这应该涵盖所有情况,甚至是仅值(仅RHS)情况。

答案 2 :(得分:1)

set tests {{FOO = BAR=BAZ} {FOO = BAR} {FOO =} {= BAR=BAZ} {= BAR} FOO}
foreach test $tests {
    # expanded regex with commentary
    regexp {(?x)
        (.*?)               # the left-hand side, may be empty
        (?:                 # start a group, but do not capture it
            \s*[:=]\s*      # the separator
            (.*)            # the value
        )?                  # end the group, and it is optional
        $                   # until the end of line: this is required because the
                            # whole regex is non-greedy due to the first
                            # quantifier being non-greedy. Without the anchor,
                            # the 2nd capture will always be the empty string.
    } $test -> var value

    puts "name='$var', value='$value'"
}

输出

name='FOO', value='BAR=BAZ'
name='FOO', value='BAR'
name='FOO', value=''
name='', value='BAR=BAZ'
name='', value='BAR'
name='FOO', value=''