Regex| PHP捕获JSON字符串中的每个非法双引号

h9a6wy2h  于 2023-09-29  发布在  PHP
关注(0)|答案(2)|浏览(143)

给定以下json字符串:{"key":"val"ue","other":"invalid ""quo"te"}
我想捕获值中的每个非法双引号。在示例中,key属性的值中有一个双引号,而other属性中有三个双引号。
我看到很多评论指出这是无效的json(正确),提供的json在接收之前应该是有效的。然而,这在我的情况下是不可能的。
假设这只会发生在值中而不是键中,我认为可以安全地假设起始序列是冒号后跟双引号。结尾序列是一个双引号,后面跟着逗号或右大括号。
我已经尝试了下面的正则表达式(在许多其他版本中),这是最接近的,所以我想要的解决方案:
/:\s?".*?(").*?[,}]/i
这正确地捕获了key属性中的一个双引号,但只捕获了“other”属性中的第一个双引号。我想它捕捉其他两个双引号以及一个单独的捕捉。
我试过的另一个正则表达式:/:\s?".*?("{1,})[^,}].*?[,}]/i这与第一个正则表达式相同,但在一次捕获中捕获两个双引号(不可取)
我的最终目标是分别捕获每个双引号,因此需要四次捕获。我想我需要的是一种让捕获组“贪婪”的方法来完成这一任务?这样它就不会在第一个双引号处停止。
我如何才能做到这一点?
我使用以下PHP代码来测试Regex:

$text = '{"key":"val"ue","other":"invalid ""quo"te"}';
$pattern = '/:\s?".*?(").*?[,}]/i';
preg_match_all($pattern, $text, $matches, PREG_OFFSET_CAPTURE);
echo '<pre>' . print_r($matches, true) . '</pre>';
puruo6ea

puruo6ea1#

你能做的就是用一个变种的诡计...
诀窍是我们匹配我们不想要的在交替的 * 左侧 *(|),然后我们捕获我们想要的在 * 右侧 *。
PCRE的好处是,左侧只有skip可用。

(?:(?:"\s*[:,]|\{)\s*"|\\"|"\s*[:}])(*SKIP)(*F)|"

See this demo at regex101
(*SKIP)(*F)的左边,所有“正确”的引号get matched (regex101)skipped 都在交替之前。任何剩余的引号都在右侧|"单独 * 匹配 *。
最后,您可以使用PREG_OFFSET_CAPTURE来获取每个“非法引用”的位置。

oo7oh9g9

oo7oh9g92#

我不会使用regex来做这件事。我会手动扫描字符串:

function detectIllegals($text)
{
    $illegals = [];
    $indideString = false;
    $len = strlen($text);
    for($i=0;$i<$len;$i++)
    {
        $c = $text[$i];
        if($c=='"')
        {
            if($indideString)
            {
                $c2 = $text[$i+1];
                if($c2==':' || $c2==',' || $c2=='}')
                    $indideString = false;
                else
                    $illegals[] = $i;
            }
            else
                $indideString = true;
        }
    }
    return $illegals;
}

$text = '{"key":"val"ue","other":"invalid ""quo"te"}';
$a = detectIllegals($text);
print_r($a);

输出量:

Array
(
    [0] => 11
    [1] => 33
    [2] => 34
    [3] => 38
)

相关问题