我如何捕获逃脱的"但不是未转义的"?

dar*_*riq 2 regex perl

假设需要由正则表达式捕获的部分由以下字符串中的PORTION指示

,"PORTION","","a",["some_string"]  
Run Code Online (Sandbox Code Playgroud)

PORTION的例子是

  • \"ABC123
  • ABC123 \"
  • \ "ABC123 \"
  • ABC\"123 \"
  • ABC123

所以字符串实际上看起来像

  • , "\" ABC123" , "", "一个",[ "some_string"]
  • ,"abc123 \"","","a",["some_string"]
  • "\" ABC123\"", "", "一个",[ "some_string"]
  • "ABC \" 123\"", "", "一个",[ "some_string"]
  • "ABC123", "", "一个",[ "some_string"]

PORTION被双引号括起来.PORTION中的双引号由反斜杠转义.我目前的模式是

my $pattern = '(.?([\\"]|[^"][^,][^"])*)';
Run Code Online (Sandbox Code Playgroud)

它产生上述例子的结果如下

  • \ "ABC123", "", "一"
  • ABC123
  • \"ABC12
  • ABC\"123 \""
  • ABC123"

该模式试图匹配不是","的序列前面的所有内容,
并且还允许捕获"
但是它没有按预期工作.我怎样才能使它工作?

Eth*_*her 5

你做得太复杂了; 没有规则说你必须在一个单片正则表达式中进行所有解析.由于您的字符串看起来像逗号分隔的序列,因此首先将其解析为:

my @fields = split /(?<!\\),/, $string;   # use comma as a delimiter (except when escaped)
Run Code Online (Sandbox Code Playgroud)

...然后相应地解析你的第一个字段:

shift @fields unless $fields[0];     # pull off the potentially null first field
$fields[0] =~ s/^"//g;               # remove the leading "
$fields[0] =~ s/(?<!\\)"$//g;        # remove the trailing " that isn't preceded by a \
Run Code Online (Sandbox Code Playgroud)

您可以通过将上面的代码包装在for循环或map()中来解析所有字段.

请注意,此代码不考虑此类事件,例如\\,(逗号在此处是有效的分隔符,即使它将错误地通过正则表达式).因此,最好为您的格式使用适当的解析器(无论它是什么).您可能需要查看Text :: CSV.

  • 使用CSV解析器会考虑引号. (2认同)