给定一串管道分隔的值(称为$psv),我希望能够按这些管道进行拆分,并填充一个数组。但是,字符串也可以包含转义管道(\|)和转义转义(\\),这两种转义都被认为仅仅是文字。对于这个问题,我有几个解决方案:
将两个转义序列替换为一些不存在的随机字符串--否则在characters
split(/\|/, $psv)中找到,通过$psv、character-by-character替换回原来的
我觉得这两种方法都能用。但是对于最大的多巴胺泛滥,我只想用一个split()呼叫来完成这个任务,而不是其他任何事情。那么,这有一个正则表达式吗?
发布于 2010-07-08 21:40:21
如果Perl支持可变宽度的后置断言,您可能可以这样做:
split(/(?<!(?<!\\)(?:\\\\)*\\)\|/, $psv);这应该匹配一个没有前面的管道字符(一个奇数反斜杠前面没有反斜杠)。但是只有固定宽度的后视断言是允许的,所以这不是一个选项。有些正则表达式专家可能会想出一些实际适用于您的方法,但我个人认为有限状态机(一次循环通过$psv )可能是一个更好的选择。
我认为您可以尝试的其他方法是拆分管道字符上的字符串,然后检查结果列表中的每个元素,看看它是否以奇数反斜杠结尾。如果是的话,将其加入到列表的下一个元素,并在它们之间添加|。基本上,你会忽略转义序列,然后返回,然后解释转义。
发布于 2010-07-08 21:39:10
您不需要在此任务中使用split。另一种选择是:
my $psv = "aaa|bbb||ccc|\\|\\|\\||\\\\\\\\\\\\";
print "$psv\n";
my @words = map { s/\\([\\|])/$1/g; $_; } ($psv =~ /(?:^|\|) ((?:\\[\\|] | [^|])*)/gx);
printf("%s\n", join(", ", @words));正则表达式看起来很吓人,但很容易解释。它匹配由管道分隔的每个单词。它要么从字符串的开头开始,要么从管道分隔符开始。然后跟随任意数目的转义序列(\ +\|之一)或任意字符(管道除外)。
map中的正则表达式只是将转义序列替换为它们真正的含义。
发布于 2010-07-09 03:52:22
是否有特定原因需要纯正则表达式解决方案?(当然,除非这个问题更多地是一个心理挑战,而不是一个实际问题)。
在实际代码中处理X分隔数据的一种正确方法是使用正确的解析器--一个非常常见的解析器是Text::CSV_XS (不要让名称欺骗您--它可以处理任何分隔字符,而不仅仅是逗号)。它将正确处理转义,以及引用。
https://stackoverflow.com/questions/3208136
复制相似问题