我将以下内容存储在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 ...
我尝试了各种正则表达式,但我总是得到相同的结果。
答案 0 :(得分:2)
您可以使用
~%(\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组中的一个或多个字词字符,然后匹配%
(.*?)
- 尽可能少地匹配和捕获第2组中任何0+字符,直到第一次出现...... (?=^%\w+%|\z)
- 开始一行,%
,1 +个字符,%
或字符串的最后(\z
可能会被{{1}替换这里因为字符串位置的结尾就够了。)展开版:
\Z
见another demo。 ~^%(\w+)%(.*(?:\R(?!%\w+%).*)*)~m
部分将以下内容与第2组匹配:
(.*(?:\R(?!%\w+%).*)*)
- .*
之后的其余部分,1 +字字符,%
子字符串%
- 匹配连续出现0次以上:
(?:\R(?!%\w+%).*)*
- 一个换行符序列\R(?!%\w+%)
),其后面没有\R
,1 +个字符和一个%
,然后...... %
- 除了换行符之外的任何0 +字符,尽可能多,直到行尾。答案 1 :(得分:1)
一种无正则表达式的方法:
$str=explode('%',$str);
$arr=[];
for($i=1;$i<count($str);$i+=2){
$arr[$str[$i]]=trim($str[$i+1]);
}
var_dump($arr);
seems to work fine.(如果您确实想要保留换行符,请移除trim
。我只是假设您没有这样做