问题来自这个帖子。我没理解错的话,楼主的要求是替换分隔符。
这里假设 csv
的规范是逗号分隔字段,允许字段中有双引号引用的字符串,如果串内要表示双引号,那么用两个双引号代替。
例如:
sdf,sdaf"asd""""""asd","asd"
对应的输出是:
sdf<$>sdafasd"""asd<$>asd
这个问题,似乎一行 Perl 就能解决:
perl -pe 'BEGIN{$sep=q{<$>}}$s="";/(?:([^",]+)(?{$s.=$1})|"(?:([^"])(?{$s.=$2})|""(?{$s.=q{"}}))*"|,(?{$s.=$sep}))+/;$_=$s;'
输入分成三类:
非双引号非逗号即 [^",]+,这类直接输出,这里用了 Perl 正则内嵌代码的功能,(?{$s.=$1}) 即把 $1 追加到 $s。 这一部分对应到正则表达式中的
(?:([^",]+)(?{$s.=$1})
由一对
non-capturing parentheses
即(?:)
包起来,里面先是模式,然后跟着的是Perl
正则表达式内嵌代码即(?{})
,用来把匹配的串追加到$2
末尾。逗号,这类输出分隔符 对应
,(?{$s.=$sep})
双引号内的文本,碰到开双引号后,碰到非双引号字符则直接输出,否则用两个双引号转义,碰到单个双引号则结束。这类用
"(([^"])|"")*"
表示。 对应"(?:([^"])(?{$s.=$2})|""(?{$s.=q{"}}))*"`