建立一個正規表示式,將JSON值中沒有雙引號的部分加上雙引號
P粉231112437
P粉231112437 2023-08-17 19:06:54
0
1
556
<p>我有很多格式錯誤的JSON字串,像這樣:</p> <pre class="brush:php;toolbar:false;">{ "id":23424938, "name":aN, "ref":aN, "jul":aN, "cat":{}, "src":[], "Code":"SA", "type":d, "spec":[i,j], "child":a }</pre> <p>我正在嘗試建立一個正規表示式來雙引號JSON值,但沒有成功。 </p> <p>我最終使用了<code>/":([^"d{[] ?[^,}]?)/</code>,它修復了所有問題,除了數組內的值,例如<code>[i,j]</code>,它不會轉換成<code>["i","j"]</code>。 </p> <p>你能幫我處理括號內的數值嗎? </p> <p>https://regex101.com/r/CGskmy/1</p>
P粉231112437
P粉231112437

全部回覆(1)
P粉755863750

這個任務會有一些困難,因為有歧義。例如,{ "x": [y] } 是變成{ "x": "[y]" } 還是變成{ "x": [" y"] }?我會假設未加引號的字串不包含JSON 控製字符,例如'[', ']', '{', '}', '"', ':', ','

我認為你可以使用命名捕獲組來完成這個任務,這是 PHP 中的一個功能,使用 PCRE 可以實現。這需要一些程式設計來執行替換。通常的 preg_replace 操作是不夠的,因為我們不會替換所有匹配項。

這是我想出來的方法。首先,我匹配引號字串並忽略它們。其次,我匹配數字並忽略它們。最後,我匹配未加引號的字串並將其儲存在名為“unquoted”的捕獲組中。請注意,PCRE 將按照這些替代項的順序嘗試匹配。只有在無法匹配引號字串和數字時,才會匹配未加引號的字串。這是這種方法的關鍵。

一旦我匹配到所有未加引號的字串,就只需要將輸出字串與替換一起拼接起來。這是透過迭代匹配項並將字串片段複製到輸出中來完成的。

<?php

$in = <<<'IN'
{
    "id":23424938,
    "name":aN,
    "ref":aN,
    "jul":aN,
    "cat":{},
    "src":[],
    "Code":"SA",
    "type":d,
    "spec":[i,j],
    "child":a
}
IN;

// 在输入字符串上匹配。我们特别关注“unquoted”匹配组。
$pattern = '/(?:"(?:\\"|[^"])+")|(?:[\d.]+)|(?P<unquoted>[^{}\[\]":,\s][^{}\[\]":,]*(?<!\s))/';
preg_match_all($pattern, $in, $matches, PREG_UNMATCHED_AS_NULL | PREG_OFFSET_CAPTURE);

// 输出字符串
$out = '';

// 跟踪输入字符串的当前索引
$ix = 0;

// 循环遍历所有未加引号的匹配项
foreach ($matches['unquoted'] as $match) {
    $str = $match[0];
    $pos = $match[1];
    if ($str !== NULL) {
        // 将输入字符串复制到输出字符串
        $out .= substr($in, $ix, $pos - $ix);
        // 将匹配的字符串复制到输出字符串,用引号括起来
        $out .= '"' . $str . '"';
        // 更新输入字符串索引
        $ix = $pos + strlen($str);
    }
}

// 将输入字符串的尾部复制到输出字符串
$out .= substr($in, $ix, strlen($in) - $ix);

// 输出字符串
echo $out;

我沒有處理完整的 JSON 數字語法,也沒有處理 JSON 語法,例如 truefalsenull。希望這個答案是一個起點,你可以根據自己的需求來調整。

InSync 提供了一個很好的正規表示式,它不使用命名捕獲組,而是命令 PCRE 跳過不需要的匹配項。

(?:
  "(?:[^\"rrreee-\x1F\x7F]|\["\/bfnrt]|\u[\dA-Fa-f]{4})*"
|
  -?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?
)
(*SKIP)(*FAIL)
|
[^{}[\]:,\s]+
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板