如何在正则表达式中包含或排除某些特定模式?

时间:2014-05-24 15:48:27

标签: php regex

我正在尝试匹配部分网址。首先,我试图只为这样的事情获得一场比赛:

http://Stackoverflow.com/questions/blah/balh.blah  
http://www.stackoverflow.com/questions/blah/balh.blah  
stackoverflow.com/questions/blah/balh.blah  
www.stackoverflow.com/  

但我也希望使用其他协议,例如httpsftp。 我自己写了一些这样的东西并不好:

((http:\/\/|https:\/\/|ftp:\/\/)*)((www.)*)([a-z]+).([a-z]{2,3})(\/)*

这个正则表达式存在很多问题,我需要弄清楚如何修复它 首先,我如何指定只有httphttps有效,而不是htttphazzzzt等? 更确切地说:

  1. 我们如何指定要包含或排除的特定字词?
  2. 现在清楚的是,(http)不会被视为单词,它只是一组字符集,因此任何只有一个字母的单词都会匹配。 我读过\b作为单词边界,但似乎\bhttp\b实际上并不意味着将http视为一个单词而不是一组字符!

    对于www部分,匹配wwwwww或任何其他数量的w! 无论我输入什么,我总是得到一个匹配! 我使用http://regex101.com/来测试正则表达式。

3 个答案:

答案 0 :(得分:2)

Hossein,你的问题中有几点和问题。

:一种。如何在正则表达式中包含或排除某些特定模式?

有很多技巧。对于简单模式,您可以指定所需内容,或指定不需要的内容,使用负字符类或负面外观。对于更复杂的模式,一个很好的起点是Match (or replace) a pattern except in situations s1, s2, s3 etc

<强> B中。如何包含或排除特定单词?

通常,为了确保特定单词属于或不属于字符串,如果您不知道其位置,则在字符串的开头处进行前瞻(或否定前瞻):

^(?=.*?MyWord)   # makes sure the word is there

^(?!.*?MyWord)   # makes sure the word is not there

<强>℃。 What is clear now, is that (http) is not treated like a word, it is just a class set of characters, so any word that has only one of those letters gets a match

这是不正确的。 (http)只会与http匹配。例如,它不匹配ptth。也许您正在考虑[http],这将是一个字符类,允许字符h,t和p匹配一次(并且[pth]会产生效率低效)

<强> d。如何匹配网址的部分

有很多解决方案,但今天我建议不要重新发明轮子。为此我可以在RegexBuddy库中建议正则表达式吗?它是

(?i)\b((?#protocol)https?|ftp)://((?#domain)[-A-Z0-9.]+)((?#file)/[-A-Z0-9+&@#/%=~_|!:,.;]*)?((?#parameters)\?[A-Z0-9+&@#/%=~_|!:,.;]*)?

下面是逐个令牌解释(我在开头添加了不区分大小写的(?i)修饰符。)

  • 断言字边界处的位置(位于前面或后面的位置,但不是两个字母,数字或下划线)\b
  • 匹配下面的正则表达式并将其匹配捕获到反向引用号1 ((?#protocol)https?|ftp)
    • 匹配此备选方案(仅在此方案失败时尝试下一个备选方案)(?#protocol)https?
      • 评论:协议(?#protocol)
      • 字面匹配字符串“http”(不区分大小写)http
      • 字面匹配字符“s”(不区分大小写)s?
        • 在零到一次之间,尽可能多次,根据需要回馈(贪婪)?
    • 或者匹配此替代方案(如果此组无法匹配则整个组都会失败)ftp
      • 字面匹配字符串“ftp”(不区分大小写)ftp
  • 匹配字符串“://”字面意思://
  • 匹配下面的正则表达式并将其匹配捕获到反向引用号2 ((?#domain)[-A-Z0-9.]+)
    • 评论:域(?#domain)
    • 匹配以下列表中的单个字符[-A-Z0-9.]+
      • 在一次和无限次之间,尽可能多次,根据需要回馈(贪婪)+
      • 字面字符“ - ”-
      • “A”和“Z”之间范围内的字符(不区分大小写)A-Z
      • “0”和“9”0-9
      • 之间范围内的字符
      • 字面字符“。”.
  • 匹配下面的正则表达式并将其匹配捕获到反向引用号3 ((?#file)/[-A-Z0-9+&@#/%=~_|!:,.;]*)?
    • 在零到一次之间,尽可能多次,根据需要回馈(贪婪)?
    • 评论:档案(?#file)
    • 字面匹配字符“/”/
    • 匹配以下列表中的单个字符[-A-Z0-9+&@#/%=~_|!:,.;]*
      • 在零和无限次之间,尽可能多次,根据需要回馈(贪婪)*
      • 字面字符“ - ”-
      • “A”和“Z”之间范围内的字符(不区分大小写)A-Z
      • “0”和“9”0-9
      • 之间范围内的字符
      • 列表中的单个字符“+&amp; @#/%=〜_ |!:,。;”+&@#/%=~_|!:,.;
  • 匹配下面的正则表达式并将其匹配捕获到反向引用号4 ((?#parameters)\?[A-Z0-9+&@#/%=~_|!:,.;]*)?
    • 在零到一次之间,尽可能多次,根据需要回馈(贪婪)?
    • 评论:参数(?#parameters)
    • 将字符“?”字面匹配\?
    • 匹配以下列表中的单个字符[A-Z0-9+&@#/%=~_|!:,.;]*
      • 在零和无限次之间,尽可能多次,根据需要回馈(贪婪)*
      • “A”和“Z”之间范围内的字符(不区分大小写)A-Z
      • “0”和“9”0-9
      • 之间范围内的字符
      • 列表中的单个字符“+&amp; @#/%=〜_ |!:,。;”+&@#/%=~_|!:,.;

答案 1 :(得分:1)

不要认为你需要外括号,例如下面是匹配http://或www。 (确保你逃避这段时间)

(http:\/\/|www\.)

另外如果你使用的是preg_match,对于jnstance的apache .htaccess会有一些细微的差别你使用一个字符来指示模式的开始和结束,如#

$regEx = '#(http:\/\/|www\.)#';

答案 2 :(得分:0)

也许你可以使用PHP过滤功能?

if (filter_var($url, FILTER_VALIDATE_URL) !== false)

FILTER_VALIDATE_URL根据RFC 2396验证URL。

http://www.php.net/manual/de/filter.filters.validate.php