正则表达式匹配URL

问题描述 投票:23回答:14

我使用以下正则表达式匹配URL:

$search  = "/([\S]+\.(MUSEUM|TRAVEL|AERO|ARPA|ASIA|COOP|INFO|NAME|BIZ|CAT|COM|INT|JOBS|NET|ORG|PRO|TEL|AC|AD|AE|AF|AG|AI|AL|AM|AN|AO|AQ|AR|AS|AT|AU|au|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BJ|BL|BM|BN|BO|BR|BS|BT|BV|BW|BY|BZ|CA|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|CR|CU|CV|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EDU|EE|EG|EH|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GOV|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|IO|IQ|IR|IS|IT|JE|JM|JO|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MF|MG|MH|MIL|MK|ML|MM|MN|MO|MOBI|MP|MQ|MR|MS|MT|MU|MV|MW|MX|MY|MZ|NA|NC|NE|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|ST|SU|SV|SY|SZ|TC|TD|TF|TG|TH|TJ|TK|TL|TM|TN|TO|R|H|TP|TR|TT|TV|TW|TZ|UA|UG|UK|UM|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|YE|YT|YU|ZA|ZM|ZW)([\S]*))/i";

但它有点搞砸了,因为它也匹配我不想要的“abc.php”。和abc ...测试。我希望它能匹配abc.com。和www.abc.com以及http://abc.com

它只需要在结尾略微调整,但我不确定是什么。 (在任何域名之后应该有一个斜杠,它现在没有检查,它只是检查\ S)

感谢您的时间。

regex
14个回答
19
投票
$search  = "#^((?#
    the scheme:
  )(?:https?://)(?#
    second level domains and beyond:
  )(?:[\S]+\.)+((?#
    top level domains:
  )MUSEUM|TRAVEL|AERO|ARPA|ASIA|EDU|GOV|MIL|MOBI|(?#
  )COOP|INFO|NAME|BIZ|CAT|COM|INT|JOBS|NET|ORG|PRO|TEL|(?#
  )A[CDEFGILMNOQRSTUWXZ]|B[ABDEFGHIJLMNORSTVWYZ]|(?#
  )C[ACDFGHIKLMNORUVXYZ]|D[EJKMOZ]|(?#
  )E[CEGHRSTU]|F[IJKMOR]|G[ABDEFGHILMNPQRSTUWY]|(?#
  )H[KMNRTU]|I[DELMNOQRST]|J[EMOP]|(?#
  )K[EGHIMNPRWYZ]|L[ABCIKRSTUVY]|M[ACDEFGHKLMNOPQRSTUVWXYZ]|(?#
  )N[ACEFGILOPRUZ]|OM|P[AEFGHKLMNRSTWY]|QA|R[EOSUW]|(?#
  )S[ABCDEGHIJKLMNORTUVYZ]|T[CDFGHJKLMNOPRTVWZ]|(?#
  )U[AGKMSYZ]|V[ACEGINU]|W[FS]|Y[ETU]|Z[AMW])(?#
    the path, can be there or not:
  )(/[a-z0-9\._/~%\-\+&\#\?!=\(\)@]*)?)$#i";

刚清理了一下。这将只匹配HTTP(s)地址,并且,只要您从IANA正确复制了所有顶级域名,只有那些标准化的(它与http://localhost不匹配)和声明的http://

最后,你应该以路径部分结束,它始终以/开头,如果它在那里。

但是,我建议你跟随Cerebrus:如果你不确定这一点,可以用更温和的方式学习regexps,并使用经过验证的模式来完成复杂的任务。

干杯,

顺便说一句:你的正则表达式也匹配something.rsomething.h(在你的例子中| TO |和| TR |之间)。我把它们留在我的版本中,因为我猜这是一个错字。

重新阅读问题:改变

  )(?:https?://)(?#

  )(?:https?://)?(?#

(有一个额外的?)匹配没有方案的'URL'。


0
投票

这是一个:

_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS

0
投票

试试Regexy::Web::Url

r = Regexy::Web::Url.new # matches 'http://foo.com', 'www.foo.com' and 'foo.com'


-1
投票
[ftp:\/\/www\/.-https:\/\/-http:\/\/][a-zA-Z0-9u00a1-uffff0]{1,3}[^ ]{1,1000} 

这在js中对我来说很好

var regex = new RegExp('[ftp:\/\/www\/.-https:\/\/-http:\/\/][a-zA-Z0-9u00a1-uffff0]{1,3}[^ ]{1,1000}');
regex.exec('https://www.youtube.com/watch?v=FM7MFYoylVs&feature=youtu.be&t=20s');

-2
投票

(http|www)\S+

只需使用此正则表达式匹配所有网址


-2
投票

只是为了添加东西。我知道这并没有完全直接回答这个具体问题,但这是我能找到的最好的地方来添加这些信息。我曾经写过一个jQuery插件,以便为了类似的目的匹配网址,但是在当前状态(随着时间的推移将更新它),它仍然会将像'http://abc.php'这样的地址视为有效。但是,如果在url start处没有http,https或ftp,则不会返回“valid”。虽然我应该澄清一下,这个jQuery方法返回一个对象而不仅仅是一个字符串或布尔值。该对象破坏了一些东西,故障中的一个是.valid布尔值。在底部的链接中查看完整的小提琴和测试。如果你只是想抓住插件去,请看下面:

jQuery插件

(function($){$.matchUrl||$.extend({matchUrl:function(c){var b=void 0,d="url,,scheme,,authority,path,,query,,fragment".split(","),e=/^(([^\:\/\?\#]+)\:)?(\/\/([^\/\?\#]*))?([^\?\#]*)(\?([^\#]*))?(\#(.*))?/,a={url:void 0,scheme:void 0,authority:void 0,path:void 0,query:void 0,fragment:void 0,valid:!1};"string"===typeof c&&""!=c&&(b=c.match(e));if("object"===typeof b)for(x in b)d[x]&&""!=d[x]&&(a[d[x]]=b[x]);a.scheme&&a.authority&&(a.valid=!0);return a}});})(jQuery);

jsFiddle示例:

http://jsfiddle.net/SpYk3/e4Ank/


12
投票

不完全是OP所要求的,但这是一个更简单的正则表达式,每次IANA引入新TLD时都不需要更新。我相信这对于大多数简单的需求来说更合适:

^(?:https?://)?(?:[\w]+\.)(?:\.?[\w]{2,})+$

没有TLD列表,localhost不匹配,子部分的数量必须> = 2且每个子部分的长度必须> = 2(fx:“a.a”将不匹配,但“a.ab”将匹配)。


6
投票

这个问题很难找到答案。我发现的正则表达式太复杂,无法理解,而且任何正则表达式都是矫枉过正而且难以实现。

最后得出:

/(\S+\.(com|net|org|edu|gov)(\/\S+)?)/

适用于http://example.comhttps://example.comexample.comhttp://example.com/foo

说明:

  • 寻找.com等
  • 匹配到空间之前的一切
  • 匹配到空间后的所有内容

5
投票

这将获得整个网址,包括?=和#/(如果存在):

/[A-Za-z]+:\/\/[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_:%&;\?\#\/.=]+/g

1
投票

使用单个正则表达式匹配URL字符串会使代码难以置信。我建议使用parse_url将URL拆分为其组件(这不是一项简单的任务),并使用正则表达式检查每个部分。


1
投票

将正则表达式的结尾更改为(/\S*)?)$应该可以解决您的问题。

解释这是做什么的 -

  • 它正在寻找/后跟一些字符(不是空格)
  • 这场比赛是可选的,?表示0或1次
  • 最后它应该后跟一个字符串的结尾(或者将它改为\b以便在单词边界上进行匹配)。

1
投票

我认为这是简单而有效的/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/


0
投票

$:美元表示字符串的结尾。 例如\ d * $将匹配以数字结尾的字符串。所以你需要添加$!


0
投票

正则表达式匹配所有网址(使用www,没有www,http或https,不含http或https,包括所有2-6个字母的顶级域名[适用于国家/地区,ex'ly','us'],端口,查询字符串和锚['#'])。这不是100%,但它比我在网上发布的任何内容都要好。

它使用第一个答案中的顶级域名,并结合我的搜索中找到的其他技术。它将返回任何有界限的有效网址,即\ b发挥作用的地方。由于尾随'/'也由\ b触发,最后一个是一个或多个'?'的匹配。

/\b((http(s?):\/\/)?([a-z0-9\-]+\.)+(MUSEUM|TRAVEL|AERO|ARPA|ASIA|EDU|GOV|MIL|MOBI|COOP|INFO|NAME|BIZ|CAT|COM|INT|JOBS|NET|ORG|PRO|TEL|A[CDEFGILMNOQRSTUWXZ]|B[ABDEFGHIJLMNORSTVWYZ]|C[ACDFGHIKLMNORUVXYZ]|D[EJKMOZ]|E[CEGHRSTU]|F[IJKMOR]|G[ABDEFGHILMNPQRSTUWY]|H[KMNRTU]|I[DELMNOQRST]|J[EMOP]|K[EGHIMNPRWYZ]|L[ABCIKRSTUVY]|M[ACDEFGHKLMNOPQRSTUVWXYZ]|N[ACEFGILOPRUZ]|OM|P[AEFGHKLMNRSTWY]|QA|R[EOSUW]|S[ABCDEGHIJKLMNORTUVYZ]|T[CDFGHJKLMNOPRTVWZ]|U[AGKMSYZ]|V[ACEGINU]|W[FS]|Y[ETU]|Z[AMW])(:[0-9]{1,5})?((\/([a-z0-9_\-\.~]*)*)?((\/)?\?[a-z0-9+_\-\.%=&]*)?)?(#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)/gi
© www.soinside.com 2019 - 2024. All rights reserved.