我将以下内容存储在 mysql 数据库中:
%URL% https://google.com
%TEXT% Hello world!
%LARGETEXT% Hello
My name is ...
I am from ...
我的目标是让 % 包裹的字符串成为 PHP 数组的键,除此之外的字符串就是值。
问题是,我的正则表达式没有提取多行字符串。
这是代码:
preg_match_all ("/%(\w+)%(.*)/", $msg, $matches);
它确实输出:
[1]=>
array(3) {
[0]=>
string(5) "BASIC"
[1]=>
string(4) "TEXT"
[2]=>
string(9) "LARGETEXT"
}
[2]=>
array(3) {
[0]=>
string(18) " https://google.de"
[1]=>
string(13) " Hello world!"
[2]=>
string(6) " Hello"
}
在第二个数组中仅显示“Hello”,而不是:
Hello
My name is ...
I am from ...
我尝试了各种正则表达式,但总是得到相同的结果。
最佳答案
您可以使用
~%(\w+)%(.*?)(?=%\w+%|$)~s
请参阅regex demo
详细信息
%
- 百分号(\w+)
- 第 1 组:一个或多个单词字符%
- 百分号(.*?)
- 第 2 组:任何 0+ 个字符(请注意,s
修饰符将使.
匹配换行符,也)尽可能少,直到第一次出现...(?=%\w+%|$)
-%
,1+ 个单词字符,%
或字符串结尾。<
一个相同的展开表达式(更有效的一个)看起来像
~%(\w+)%([^%]*(?:%(?!\w+%)[^%]*)*)~
(不需要 s
修饰符)。请参阅regex demo .
[^%]*(?:%(?!\w+%)[^%]*)*
匹配 %
之外的任何 0+ 个字符,然后匹配 0 个或多个后续出现的 %
,后跟不带 1 个以上单词字符,然后 %
后跟除 %
之外的任何 0+ 个字符.
如果您的条目始终出现在不同行的开头,您可以使用
~^%(\w+)%(.*?)(?=^%\w+%|\z)~sm
查看此regex demo
详细信息
^
- 匹配行的开头(由于m
修饰符)%(\w+)%
- 匹配%
,然后将一个或多个单词字符匹配并捕获到第 1 组中,然后匹配%
(.*?)
- 将尽可能少的任意 0+ 个字符匹配并捕获到第 2 组中,直到第一次出现...(?=^%\w+%|\z)
- 行首,%
,1+ 个单词字符,%
或者字符串的最末尾(\z
可能会替换为\Z
,因为只需字符串位置的末尾就足够了)。
展开版本:
~^%(\w+)%(.*(?:\R(?!%\w+%).*)*)~m
参见another demo 。 (.*(?:\R(?!%\w+%).*)*)
部分将以下内容匹配到第 2 组:
.*
-%
之后的行的其余部分,1+ 个单词字符,%
子字符串(?:\R(?!%\w+%).*)*
- 匹配 0 次以上连续出现的以下内容:\R(?!%\w+%)
- 没有%
的换行序列 (\R
),1+单词字符和后面的%
然后....*
- 除换行符之外的任何 0+ 个字符,尽可能多,直到行尾。
关于php - preg_match_all - 从模板中提取键/值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45698546/