簡體   English   中英

正則表達式中的多種模式

[英]Multiple patterns within regex

我有一個json,我需要匹配所有“文本”鍵以及“ html”鍵。

例如,json可能如下所示:

[{
"layout":12,
"text":"Lorem",
"html":"<div>Ipsum</div>"
}]

或可能如下所示:

[{
"layout":12,
"settings":{
    "text":"Lorem",
    "atts":{
        "html":"<div>Ipsum</div>"
    }
}
}]

json並不總是使用相同的結構,因此我必須匹配鍵並使用preg_match_all獲取其值。 我嘗試了以下方法來獲取“文本”鍵的值:

preg_match_all('|"text":"([^"]*)"|',$json,$match_txt,PREG_SET_ORDER);

上面的方法可以很好地匹配單個鍵。 當要匹配第二個鍵(在這種情況下為“ html”)時,它根本不起作用。 我嘗試了以下方法:

preg_match_all('|"text|html":"([^"]*)"|',$json,$match_txt,PREG_SET_ORDER);

您能否給我一些提示,為什么OR運算符(text | html)不起作用? 奇怪的是,當我在在線測試器中對其進行測試時,上述(多模式)正則表達式工作正常,但在我的php文件中卻無法正常工作。

固定text|html

您應該將text|html添加到組中,否則將查找"texthtml"

|"(text|html)":"([^"]*)"|

定界符

盡管您在表達式中使用了豎線( | ),但當前無法使用分隔符。 您應該將定界符更改為其他名稱,這里我使用/

/"(text|html)":"([^"]*)"/

如果仍要使用管道作為分隔符,則應在表達式中對管道進行轉義。

|"(text\|html)":"([^"]*)"|

如果您不想手動轉義它, preg_quote()可以為您完成。

$exp = preg_quote('"(text|html)":"([^"]*)"');
preg_match_all("|{$exp}|",$json,$match_txt,PREG_SET_ORDER);

解析JSON

盡管該正則表達式將起作用,但它將需要額外的解析,為此使用遞歸函數更有意義。

json_decode()將JSON字符串解碼為相對數據類型。 在下面的示例中,我傳遞了一個附加參數true ,這意味着我將獲得一個關聯array ,在該array中通常會獲得一個object

一旦findKeyData() ,它將遞歸地調用自身並遍歷所有數據,直到找到指定的鍵。 如果不是,則返回null

function findKeyData($data, $key) {
    foreach ($data as $k => $v) {
        if (is_array($v)) {
            $data = findKeyData($v, $key);
            if (! is_null($data)) {
                return $data;
            }
        }
        if ($k == $key) {
            return $v;
        }
    }
    return null;
}

$json1 = json_decode('[{
"layout":12,
    "text":"Lorem",
    "html":"<div>Ipsum</div>"
    }]', true);
$json2 = json_decode('[{
"layout":12,
    "settings":{
    "text":"Lorem",
    "atts":{
        "html":"<div>Ipsum</div>"
    }
}
}]', true);

var_dump(findKeyData($json1, 'text')); // Lorem
var_dump(findKeyData($json1, 'html')); // <div>Ipsum</div>
var_dump(findKeyData($json2, 'text')); // Lorem
var_dump(findKeyData($json2, 'html')); // <div>Ipsum</div>
preg_match_all('/"(?:text|html)":"([^"]*)"/',$json,$match_txt,PREG_SET_ORDER);

print $match_txt[0][0]." with group 1: ".$match_txt[0][1]."\n";
print $match_txt[1][0]." with group 1: ".$match_txt[1][1]."\n";

返回:

$ php -f test.php
"text":"Lorem" with group 1: Lorem
"html":"<div>Ipsum</div>" with group 1: <div>Ipsum</div>

需加上括號(?:text|html) ; 沒有它,我無法在https://regex101.com上運行 ?:表示不捕獲括號的內容(即結果中不可用)。

我還用正斜杠替換了管道( | )分隔符 ,因為您在正則表達式中也有管道。 另一種選擇是在正則表達式中轉義管道: |"(?:text\\|html)":"([^"]*)"|

我看不到使用正則表達式解析有效json字符串的任何理由:

array_walk_recursive(json_decode($json, true), function ($v, $k) {
    if ( in_array($k, ['text', 'html']) )
        echo "$k -> $v\n";
});

演示

您使用管道| 字符作為分隔符,我認為這會破壞您的正則表達式。 它是否可以使用其他分隔符(例如

preg_match_all('#"text|html":"([^"]*)"#',$json,$match_txt,PREG_SET_ORDER);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM