我有类似以下字符串的字符串,这些字符串称为 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
如何将这些正则表达式组合在一起,使一个正则表达式可以覆盖所有情况?
答案 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=''