我在Tcl中使用以下行来解析以逗号分隔的字段行。可以引用某些字段,以便它们可以包含逗号:
set line {12,"34","56"}
set fresult [regsub -all {(\")([^\"]+)(\",)|([^,\"]+),} $line {{\2\4} } fields]
puts $fields
{12} {34} "56"
(引用最后一个字段而不是括号,这有点奇怪,但这不是问题)
但是,当引号中有逗号时,它不起作用:
set line {12,"34","56,78"}
set fresult [regsub -all {(\")([^\"]+)(\",)|([^,\"]+),} $line {{\2\4} } fields]
puts $fields
{12} {34} "{56} 78"
我希望: {12} {34} {56,78}
我的正则表达式是否有问题,或者有什么东西正在进行?
答案 0 :(得分:5)
我想到的一个选项是在TclLib中使用CSV功能。 (没有理由重新发明轮子,除非你必须......)
http://tcllib.sourceforge.net/doc/csv.html
文档摘录
:: csv :: split? - 替代?线 {sepChar,} {delChar“}转换为 将CSV格式的行转换为列表 行中包含的值。该 用于分隔值的字符 彼此之间可以定义 来电者,通过sepChar,但这是 可选的。默认值为“,”。该 引用字符可以定义 调用者,但这是可选的。该 默认为'“'。如果选项 -alternate是spcified一个稍微不同的语法用于解析 输入。这个语法解释如下, 在格式部分。
答案 1 :(得分:2)
这个问题似乎是一个额外的逗号:你只接受带引号的字符串,如果它们后面有一个逗号。并对非引用的标记执行相同的操作,这有效:
set fresult [regsub -all {(\")([^\"]+)(\")|([^,\"]+)} $line {{\2\4} } fields]
^(no commas)^
工作示例: http://ideone.com/O2hss
你可以放心地将逗号保留在模式之外 - 正则表达式引擎会热衷于搜索新匹配:它将跳过一个它无法匹配的逗号,并从下一个字符开始。
奖励:这也将使用\"
处理转义引号(如果您需要,您应该能够使用""
代替\\.
轻松适应):
set fresult [regsub -all {"((?:[^"\\]|\\.)+)"|([^,"]+)} $line {{\1\2} } fields]
答案 2 :(得分:0)
正如你对@Kobi所说,如果你允许空字段,你应该允许空字符串“”
{((\")([^\"]*)(\")|([^,\"]*))(,|$)}
其中感兴趣的字段转移到3和5
扩展:{ ( (\")([^\"]*)(\") | ([^,\"]*) ) (,|$) }
我承认,我不知道tcl是否允许(?:)非捕获分组。
答案 3 :(得分:0)
使用以下regsub
% set line {12,"34","56,78"}
% regsub -all {(,")|(",)|"} $line " " line
% set line
12 34 56,78 <<< Result
此处所有出现的,"
或",
或"
(按顺序)都会被空格取代