[英]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
添加到組中,否則將查找"text
或html"
。
|"(text|html)":"([^"]*)"|
盡管您在表達式中使用了豎線( |
),但當前無法使用分隔符。 您應該將定界符更改為其他名稱,這里我使用/
。
/"(text|html)":"([^"]*)"/
如果仍要使用管道作為分隔符,則應在表達式中對管道進行轉義。
|"(text\|html)":"([^"]*)"|
如果您不想手動轉義它, preg_quote()可以為您完成。
$exp = preg_quote('"(text|html)":"([^"]*)"');
preg_match_all("|{$exp}|",$json,$match_txt,PREG_SET_ORDER);
盡管該正則表達式將起作用,但它將需要額外的解析,為此使用遞歸函數更有意義。
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.