我必须用Perl中的regex解析当前行"abc\",","\","
,
得到这个结果"abc\","
和"\","
我这样做
while (/(\s*)/gc) {
if (m{\G(["])([^\1]+)\1,}gc){
say $2;
}
}
但这是错误的,因为这个正则表达式是最后一个", 我的问题是,我怎样才能跳过这个"并停在第一个",?
答案 0 :(得分:2)
以下程序根据您的规范执行匹配:
while (<>) {
@arr = ();
while (/("(?:\\"|[^"])*")/) {
push @arr, $1;
$_ = $';
}
print join(' ', @arr), "\n";
}
输入文件input.txt
:
"abc", "def"
"abc\",","\","
输出:
$ ./test.pl < input.txt
"abc" "def"
"abc\"," "\","
可以改进以更严格地匹配,因为在这种形式中可能有许多输入可能是不可取的,但它用作第一指针。此外,最好将CSV
文件与相应的模块匹配,而不是使用正则表达式,但是您没有说明您的输入是否真的是CSV
文件。
答案 1 :(得分:2)
不要重新发明轮子。如果您有CSV,请使用CSV解析器。
use Text::CSV_XS qw( );
my $string = '"abc\",","\","';
my $csv = Text::CSV_XS->new ({ binary => 1, auto_diag => 1 });
$csv->parse($_)
my @fields = $csv->fields();
答案 2 :(得分:1)
正则表达式不是执行此任务的最佳工具。标准Text::ParseWords模块可以轻松完成此任务。
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Text::ParseWords;
my $line = '"abc\",","\","';
my @fields = parse_line(',', 1, $line);
for (0 .. $#fields) {
say "$_: $fields[$_]"
}
输出结果为:
0: "abc\","
1: "\","
答案 3 :(得分:0)
split /(?<!\\)",(?<!\\)"/, $_
(之前用s/^"// && s/"$//;
清除$ _的边界,因为包含外部引号并不需要在输入字符串的定义中,但你有它们)
直接返回你想要的数组(不需要外部循环,因为循环在核心perl函数split
内,你可以根据字符串的提供方式在逗号周围添加\ s *)。
..但(实际上只是你没有提到的一个注释)可能会有更深层次的案例
如果\"
表示"
,\\
意味着\
,那么您可能有\\\"
和\\"
,最后一个({1}}更常见的是,偶数\
前"
)与一行regexp复杂,因为后视是针对固定大小实现的,而不受支持的正则表达形式(?<!\\(?:\\\\)*)"
也可能会很好反斜杠后没有作为来自序列\"
的转义引用\\"
的字符串分隔符,是不适用的,并且是一个效率较低的代码,但是这个边际考虑是关于{{1必须假设解释。