如何复用现有Perl正则应用,实现单行代码解析CSV(弃用CSV库)?
用Perl单行正则解析CSV,复用你的现有逻辑
嘿,这事儿太适合Perl来干了——毕竟“一行干翻”是Perl的传统艺能,而且你已经有现成的正则基础,复用起来超顺手!我给你拆解两种场景的实现方式:一种是处理脚本里的字符串变量(比如你示例里的$text),另一种是直接处理CSV文件的单行脚本。
1. 处理脚本内的字符串变量(单行实现)
针对你给出的示例文本,我们可以把字段拆分、转义处理浓缩成一行。核心思路是用全局匹配正则抓取所有字段,再用map快速处理转义引号:
my @fields = map { $_ // '' =~ s/\\"/"/gr } $text =~ /(?:^|,)(?:"([^"\\]*(?:\\.[^"\\]*)*)"|([^,]*))/g;
拆解一下这行的逻辑:
- 正则部分:
/(?:^|,)(?:"([^"\\]*(?:\\.[^"\\]*)*)"|([^,]*))/g
专门匹配CSV的三种字段类型:- 带引号的字段(包含转义引号
\"和逗号):捕获引号内部的内容到第一组 - 不带引号的普通字段:直接捕获到第二组
- 空字段(比如
""或者连续逗号之间的空白):捕获为空字符串
- 带引号的字段(包含转义引号
- map处理:
$_ // '':把正则匹配可能返回的undef(比如空字段的情况)转成空字符串s/\\"/"/gr:用Perl的r修饰符直接返回替换后的结果,把转义引号\"还原成普通双引号
拿你的示例文本测试:
my $text = '"",hi there,"","2018-04-23,\" 13:14:53",...'; my @fields = map { $_ // '' =~ s/\\"/"/gr } $text =~ /(?:^|,)(?:"([^"\\]*(?:\\.[^"\\]*)*)"|([^,]*))/g; # 输出@fields会得到:("", "hi there", "", "2018-04-23," 13:14:53", "...")
2. 直接处理CSV文件的单行脚本
如果要复用你的正则批量处理CSV文件,可以直接写Perl命令行单行脚本,不用写完整脚本:
perl -nE 'my @fields = map { $_//"" =~ s/\\"/"/gr } /(?:^|,)(?:"([^"\\]*(?:\\.[^"\\]*)*)"|([^,]*))/g; say join("\t", @fields)' your_file.csv
这个单行脚本的作用:
-n:让Perl自动遍历输入文件的每一行-E:启用Perl的新特性(比如say函数,自动加换行)- 每行拆分后用制表符
\t分隔输出,方便你查看或者导入其他工具
注意事项
- 如果你之前的正则已经适配了特殊场景(比如字段内的换行符),直接把上面的正则替换成你现成的就行,
map里的转义处理可以按需调整 - 虽然正则能覆盖绝大多数CSV场景,但CSV标准里的极端情况(比如字段内有未转义的换行)可能还是需要特殊处理——不过你已经有正则解析的经验,应该能轻松应对!
内容的提问来源于stack exchange,提问作者petom
相关产品推荐
相关产品推荐

