理论上不错,实践上很糟糕
通过CSV,我将假设您的意思是RFC 4180中描述的约定。
匹配基本CSV数据很简单:
"data", "more data"
注意:顺便说一句,对于非常简单且结构良好的数据,使用.split('/ n')。split('“')函数效率要高得多。正则表达式可作为NDFSM(不确定性有限)状态机),一旦您开始添加转义字符(如转义字符)等极端情况,就会浪费大量时间进行回溯。
例如,这是我找到的最全面的正则表达式匹配字符串:
re_valid = r"""
# Validate a CSV string having single, double or un-quoted values.
^ # Anchor to start of string.
\s* # Allow whitespace before value.
(?: # Group for value alternatives.
'[^'\\]*(?:\\[\S\s][^'\\]*)*' # Either Single quoted string,
| "[^"\\]*(?:\\[\S\s][^"\\]*)*" # or Double quoted string,
| [^,'"\s\\]*(?:\s+[^,'"\s\\]+)* # or Non-comma, non-quote stuff.
) # End group of value alternatives.
\s* # Allow whitespace after value.
(?: # Zero or more additional values
, # Values separated by a comma.
\s* # Allow whitespace before value.
(?: # Group for value alternatives.
'[^'\\]*(?:\\[\S\s][^'\\]*)*' # Either Single quoted string,
| "[^"\\]*(?:\\[\S\s][^"\\]*)*" # or Double quoted string,
| [^,'"\s\\]*(?:\s+[^,'"\s\\]+)* # or Non-comma, non-quote stuff.
) # End group of value alternatives.
\s* # Allow whitespace after value.
)* # Zero or more additional values
$ # Anchor to end of string.
"""
它合理地处理单引号和双引号值,但不处理值的换行符,转义引号等。
资料来源:堆栈溢出-如何使用JavaScript解析字符串
一旦引入常见的边缘情况,这将成为一场噩梦。
"such as ""escaped""","data"
"values that contain /n newline chars",""
"escaped, commas, like",",these"
"un-delimited data like", this
"","empty values"
"empty trailing values", // <- this is completely valid
// <- trailing newline, may or may not be included
仅换行符作为值的边缘情况就足以破坏在野生环境中发现的基于RegEx的解析器的99.9999%。唯一“合理”的选择是对基本控制/非控制字符(即终端与非终端)标记化使用RegEx匹配,并与用于更高级别分析的状态机配对。
资料来源:经验,即广泛的痛苦和折磨。
我是jquery-CSV的作者,jquery-CSV是世界上唯一基于JavaScript的,完全符合RFC的CSV解析器。我花了几个月的时间解决这个问题,与许多有才华的人交谈,并且尝试了很多不同的实现,包括对核心解析器引擎的3次完全重写。
tl; dr-故事的寓意,除最简单和严格的常规(即III类)语法外,PCRE本身就很烂。尽管如此,它对于标记终端字符串和非终端字符串很有用。