Php 如何匹配在特定子字符串之后出现的多个子字符串?
我试图从nginx配置文件中读取服务器名称 我需要在这样一行中使用正则表达式: 服务器名称this.com www.this.com someother-example.com 我正在使用PHP的Php 如何匹配在特定子字符串之后出现的多个子字符串?,php,regex,preg-match-all,Php,Regex,Preg Match All,我试图从nginx配置文件中读取服务器名称 我需要在这样一行中使用正则表达式: 服务器名称this.com www.this.com someother-example.com 我正在使用PHP的preg\u match\u all(),到目前为止,我尝试了不同的方法: /^(?:server_name[\s]*)(?:(.*)(?:\s*))*;$/m // no output /^(?:server_name[\s]*)((?:(?:.*)(?:\s*))*);$/m // this.c
preg\u match\u all()
,到目前为止,我尝试了不同的方法:
/^(?:server_name[\s]*)(?:(.*)(?:\s*))*;$/m
// no output
/^(?:server_name[\s]*)((?:(?:.*)(?:\s*))*);$/m
// this.com www.this.com someother-example.com
但我找不到合适的方法将域列为单独的值
[
0 => 'this.com',
1 => 'www.this.com',
2 => 'someother-example.com'
]
正如鲍勃的叔叔所写:
(?:服务器名称|\G(?!^))\s*\K[^;|\s]+
真有办法 简单的英语要求是提取紧跟在
server\u name
之后的空格分隔字符串,然后提取几个空格
动态组合\G
(从开始开始/从最后一场比赛结束后继续)和\K
(重新开始全串比赛)将成为当今的英雄
代码:()
输出:
array (
0 => 'this.com',
1 => 'www.this.com',
2 => 'someother-example.com',
)
模式说明:
(?: # start of non-capturing group (to separate piped expressions from end of the pattern)
server_name + # literally match "server_name" followed by one or more spaces
| # OR
\G(?!^) # continue searching for matches immediately after the previous match, then match a single space
) # end of the non-capturing group
\K # restart the fullstring match (aka forget any previously matched characters in "this run through")
[^; ]+ # match one or more characters that are NOT a semicolon or a space
您之所以看到\G(?!^)
而不是\G
(记录在案,这在示例输入中可以很好地工作),是因为\G
的默认行为可能会从两个不同的点进行匹配
如果要使用my pattern的裸版\G
并在输入字符串的前面添加一个空格,则不会进行预期的匹配\G
将成功地从字符串的开头开始,然后匹配单个空格,然后通过求反字符类[^;]
匹配服务器名称
因此,禁用\G
的“从字符串开头开始”功能可以使模式更加稳定/可靠/准确
preg\u match\u all()
返回一个匹配数组。第一个元素[0]
是完整字符串匹配的集合(匹配的内容与捕获组无关)。如果存在任何捕获组,则它们从[1]
开始,并随每个新组递增
因为在定位要提取的子字符串之前需要匹配server\u name
,所以使用捕获组将意味着输出数组过多,并且完整字符串匹配的子数组不可用
要提取所需的以空格分隔的子字符串并从结果中省略server\u name
,\K
用于在查找所需子字符串之前“忘记”匹配的字符
如果不使用\K
清除不需要的前导字符,输出将是:
array (
0 => 'server_name this.com',
1 => ' www.this.com',
2 => ' someother-example.com',
)
如果有人将我的答案与用户3776824或HamZa的答案进行比较:
server\u name
后面有4个空格,因此我可以使用一个精确的量词{4}
,但在这里选择了一点灵活性。\s*
不是最理想的,因为匹配时总会有“一个或多个空格”“匹配。我对\s
没有问题,但要明确的是,它确实匹配空格、制表符、换行符和换行符(?!^)
——一种负前瞻——而不是(?——一种负前瞻,因为它用更少的字符完成相同的工作。你会更常见地看到有经验的正则表达式工匠使用\G(?!^)
|
)来分隔值。user3776824的模式除了分号和空格之外,实际上还排除了管道——尽管我不期望基于示例数据的结果会有任何负面影响。模式中的管道不应该被写入(?:server|u name |\G(?!如果它们用空格符号分开,为什么不用空格符号分开呢?谢谢!没有“@user3776824啊,那是我的错别字!我本想写(?!^)
也应该这样做:)鲍勃的叔叔和范妮的婶婶(仅限代码)答案在Stackoverflow上的价值很低,因为它们对未来数千名研究人员的教育/授权作用微乎其微。请尽最大努力解释您在此处发布的每个答案。您会发现很少有研究人员对什么\G
有任何线索(继续元字符)是的。这突出了当志愿者使用评论提供答案时,Stackoverflow的一个反复出现的问题。在这种情况下,最初提供工作解决方案的人没有给出很好的解释。
array (
0 => 'server_name this.com',
1 => ' www.this.com',
2 => ' someother-example.com',
)