【问题标题】:preg_match_all subdomains under special conditionspreg_match_all 特殊条件下的子域
【发布时间】:2015-05-23 08:34:51
【问题描述】:

更新:

我正在使用这个正则表达式:

/[^a-z^-^0-9^@^%^\/^:^\.^-]((?<!w\.)(?!w+\.)([0-9a-z][0-9a-z\-]*\.){2,}[a-z]+)(["|\s|<]|$)/i

当字符串只是域而没有其他内容时,正则表达式有一个小问题,在新行中相互列出

例如:

$string = 'sub84.example4.com
sub-example.example84.net
sub-84example.example-h1.org
www-example4124.domain.com
sub.example-www.com';

所有域都应该匹配,但他当前的正则表达式只匹配sub-example.example84.net和www-example4124.domain.com

我还想添加更多条件:

1) 域的字母必须小,不能大写(当前的不在乎) 例如:Sub.example.Com 不行。

2) 在域之前没有 =SPACE (SPACE (" :SPACE,在域之后没有 SPACE) 或 SPACE= ") SPACE:。

前:

$string = '

text = sub1.example.com text
text ( sub2.example.com text
text sub3.example.com = text
text sub4.example.com ) text
text ("sub5.example.com text
text sub6.example.com") text
text : sub7.example.com text
text sub8.example.com : text

';

没有一个是好的

3) 排除 .info .biz .tv tlds

谢谢。

【问题讨论】:

  • 提供您尝试解决此问题的尝试。
  • 先用DOMDocument提取href属性和纯文本部分。之后且仅在应用模式之后。
  • @hwnd 这很糟糕(如果不是最糟糕的话),这就是我需要帮助的原因..但无论如何,我把我的代码放在这个问题上,谢谢。
  • 提出一个新问题,而不是重复使用旧问题。
  • 你真正的目的是什么?例如-您想从网页获取所有域,您有一个 tld 区域文件并希望从那里解析所有域或...(在此处输入一些内容),因为这可能比使用昂贵的操作更好,例如用正则表达式匹配文本?

标签: php regex preg-match-all subdomain


【解决方案1】:

这是一个

/[^a-z^-^0-9^@^\/^:^\.^-]((?<!w\.)(?!w+\.)([0-9a-z][0-9a-z\-]*\.)+[a-z]+)(["\s<]|$)/ig

【讨论】:

  • 这个问题有一个开放的赏金价值+50声望,谢谢。
  • ^ 到底是什么鬼?
  • @HamZa:不,问题中的正则表达式从这个答案中复制以添加更多要求。
【解决方案2】:

我不太明白这样做的目的或数量惊人的条件,但你可以试试这个(相当长的一个......):

(?<!http://)(?<!https://)(?<!www\.)(?![^\s<>]*[:@/])(?<![(=:] )(?<!\(")(?:(?<=[\s">])|^)(?:[a-z0-9-]+\.){2}(?!info|biz|tv)[a-z]+(?=[\s"<]|$)(?! [=):])(?!"\))

regex101 demo


细分:

(?<!http://)(?<!https://)(?<!www\.)        # Prevent http:// https:// and www.
(?![^\s<>]*[:@/])                          # Prevent : @ /
(?<![(=:] )(?<!\(")                        # Prevent '( ' '= ' etc
(?:(?<=[\s">])|^)                          # Ensure there's ' ', '>', '"' or beginning of line
(?:[a-z0-9-]+\.){2}(?!info|biz|tv)[a-z]+   # Main match, alphanumerics and -, 2 parts + tlds (excluding info, biz, tv
(?=[\s"<]|$)                               # Ensure there's ' ', '<', '"' or end of line
(?! [=):])(?!"\))                          # Prevent ' )' ' =' etc

【讨论】:

  • 非常感谢,你的正则表达式对我来说是完美的,你是对的,不需要所有这些条件,我会减少它,再次感谢:)
【解决方案3】:

随着正则表达式的发展,前瞻和后瞻是昂贵的。你可以在没有这个怪物的情况下做到这一点:

(?:^[^0-9a-zA-Z]??|[^=(:][^0-9a-zA-Z\-]|=[^ 0-9a-zA-Z]|\([^ "0-9a-zA-Z]|:[^ 0-9a-zA-Z]|[^0-9a-zA-Z]-)((?:[0-9a-z][0-9a-z\-]*\.){2,}(?:[ac-hj-su-z][a-z]*|b[a-z]?|bi[a-y]|b[a-z]{3,}|i[a-z]{0,2}|inf[a-np-z]|i[a-z]{4,}|t|t[a-uw-z]|t[a-z]{2,}))(?:[^a-zA-Z "]| [^=:)]|"[^)]|[ "]?$)

这将强制每个 1 使用小写子域,正确删除您在 2 中列出的所有前置条件和后置条件,并禁止 .biz em>、.info 和 .tv 每 3.

但是您需要将它与m 修饰符一起使用,以便^ 和$ 可以匹配每行,而不仅仅是输入的开头和结尾。因此,您需要执行以下操作:

preg_match_all('/(?:^[^0-9a-zA-Z]??|[^=(:][^0-9a-zA-Z\-]|=[^ 0-9a-zA-Z]|\([^ "0-9a-zA-Z]|:[^ 0-9a-zA-Z]|[^0-9a-zA-Z]-)((?:[0-9a-z][0-9a-z\-]*\.){2,}(?:[ac-hj-su-z][a-z]*|b[a-z]?|bi[a-y]|b[a-z]{3,}|i[a-z]{0,2}|inf[a-np-z]|i[a-z]{4,}|t|t[a-uw-z]|t[a-z]{2,}))(?:[^a-zA-Z "]| [^=:)]|"[^)]|[ "]?$)/m', $string, $foo);

让我快速解释一下正则表达式的各个部分,希望这很有意义:

第一部分是替代查看子域之前的内容,它阻止了您在 2 中列出的先决条件:(?:^[^0-9a-zA-Z]??|[^=(:][^0-9a-zA-Z\-]|=[^ 0-9a-zA-Z]|\([^ "0-9a-zA-Z]|:[^ 0-9a-zA-Z]|[^0-9a-zA-Z]-) 这是一个非捕获组,它将匹配 6 个选项中的 1 个:

  1. 行首,可能是 1 个非字母数字字符
  2. '='、'(' 或 ':' 以外的字符后跟非字母数字非'-' 字符
  3. '=' 后跟一个非空格和非字母数字字符
  4. '(' 后跟除'"'、空格或字母数字以外的字符
  5. ':' 后跟一个非空格和非字母数字字符
  6. 非字母数字字符后跟'-' 字符

捕获中的第二部分是您的原始子域减去后缀匹配:(?:[0-9a-z][0-9a-z\-]*\.){2,}

第三部分也在捕获中,消除了带有"biz"、"info" 或"tv" 后缀的子域:(?:[ac-hj-su-z][a-z]*|b[a-z]?|bi[a-y]|b[a-z]{3,}|i[a-z]{0,2}|inf[a-np-z]|i[a-z]{4,}|t|t[a-uw-z]|t[a-z]{2,}) 这是一个非捕获组,有 10 个选项:

  1. 'b'、'i' 或 't' 以外的字符后跟任意数量的小写字符
  2. 'b' 和其他一些小写字符
  3. "bi" 后跟非'z' 字符
  4. 'b' 后跟 3 个或更多小写字符
  5. 'i' 后跟 2 个或更少的小写字符
  6. "inf" 后跟非'o' 字符
  7. 'i' 后跟 4 个或更多小写字符
  8. 't' 字符
  9. 't' 后跟非'v' 字符
  10. 't' 后跟 2 个或更多小写字符

最后一部分阻止您在 2 中列出的后置条件:(?:[^a-zA-Z "]| [^=:)]|"[^)]|[ "]?$) 它是一个非捕获组,有 4 个选项:

  1. 不是空格、'"'、小写或大写字符的字符
  2. 一个空格后跟一个不是'='、':' 或')' 的字符
  3. '"' 后跟非')' 字符
  4. 非空格非'"' 后跟行尾

【讨论】:

  • +1 非常感谢,非常感谢您的帮助,您编写正则表达式的方式对我来说非常先进,我想我需要一段时间来学习如何处理这样的正则表达式。跨度>
  • @user2203703 是的 :) 我不知道它是否像过时一样先进。 regex 的 C++11 实现仍然不支持前瞻或后瞻,因此您必须了解解决方法。非捕获组选项工作得很好,在我看来他们正在搜索的内容更明确,但它们的代价是更冗长,所以在支持前瞻和后瞻的语言上,不要'不要觉得自己做错了什么,这只是偏好。
猜你喜欢
  • 2018-08-21
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-01
  • 1970-01-01
  • 2016-08-09
  • 2015-04-09
相关资源
最近更新 更多