使用 PCRE 正则表达式从类似 CSV 的字符串中提取值,包括空字段

Extract values from CSV-like string including empty fields with PCRE regex

我尝试从多个类似 csv 的简单数据列字符串中捕获包括(!)空列的列值,用分号分隔。即使我知道正则表达式不是最好的方法并且显式 csv 解析器会做得更好,在这种情况下我别无选择,只能使用 PRCE 正则表达式来构建 html table <td> 个来自该数据的组。

应该(仍然)有效的更糟糕的示例如下所示:

;testvalue;"testvalue";"test "val"ue";test value;

... 字面上应该这样解释:

empty | testvalue | testvalue | test "val"ue | test value | empty

...最终呈现为这个(不是问题的一部分):

<td>empty</td>
<td>testvalue</td>
<td>testvalue</td>
<td>test"val"ue</td>
<td>test value</td>
<td>empty</td>

(按照@anubhava 的要求进行更新)

可悲的是,还有另一个 downer 随之而来:将实施它的系统有一个固定的方式来处理字符串。它只会识别并且只会改变捕获的字符串组。字符串的任何其他未注册部分将直接与其余部分 原样 一起打印出来。这意味着:我们需要注册正则表达式中的分号,即使我们不希望它们被打印出来,而是通过忽略它们的匹配组来删除它们。

通常只打印捕获的组就可以了,但是这里不行。仅捕获值将导致此输出:

;;;;;
<td>empty</td>
<td>testvalue</td>
<td>testvalue</td>
<td>test"val"ue</td>
<td>test value</td>
<td>empty</td>

也许我们需要在另一组中先捕获整个字符串,或者我们需要在另一组中捕获分号以便稍后在打印输出时将其丢弃? ...

尝试以下 PCRE 正则表达式:

\"(?:.*?)\"(?=;|$)|(?<=(?:;))(?:.*?)(?=;|$)|^(?:[^;]*?)(?=;)

从示例字符串 ;testvalue;"testvalue";"test value";test value; 正则表达式将捕获:

Match 1:             
Match 2:    testvalue
Match 3:    "testvalue"
Match 4:    "test value"
Match 5:    test value
Match 6:            

https://regex101.com/r/sU2jK5/2

查看演示

您可以使用这个更简单的正则表达式,在第三个捕获组中使用包含分号的后视:

$str = ';testvalue;"testvalue";"test "val"ue";test value;';
preg_match_all('/(?<=;|^)("?)([^;]*)(;|$)/', $str, $matches);

print_r($matches[2]);

(?<=;|^) 是一个积极的回顾,以确保我们仅在行开始或 ;.

之后才匹配 [^;]*

输出:

Array
(
    [0] =>
    [1] => testvalue
    [2] => testvalue
    [3] => test "val"ue
    [4] => test value
    [5] =>
)

RegEx Demo

并获得所需的 HTML:

echo "<td>" . implode("</td>\n<td>", $matches[2]) . "</td>\n";

<td></td>
<td>testvalue</td>
<td>testvalue</td>
<td>test "val"ue</td>
<td>test value</td>
<td></td>