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

我试图从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.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',
    )