正则表达式匹配URL

时间:2009-07-17 07:32:24

标签: regex

我使用以下正则表达式来匹配网址:

$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)

谢谢你的时间。

16 个答案:

答案 0 :(得分: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正确复制了所有顶级域名,只有那些标准化的域名(它将匹配{{1 }})和 with http://localhost声明。

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

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

干杯,

顺便说一下:您的正则表达式也会匹配http://something.r(在您的示例中介于| TO |和| TR |之间)。我把它们留在我的版本中,因为我猜这是一个错字。

重新阅读问题:更改

something.h

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

(有一个 )(?:https?://)?(?# 额外的)来匹配没有方案的“网址”。

答案 1 :(得分:12)

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

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

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

答案 2 :(得分:6)

这个问题很难找到答案。我发现的正则表达式太复杂了,无法理解,而且正则表达式更难以实现。

最后提出:

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

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

说明:

  • 寻找.com等
  • 匹配前面的所有内容
  • 匹配空间后的所有内容

答案 3 :(得分:5)

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

// looping through list of videos
for (unsigned int i = 0; i < img_loc.size(); i++)
{
    string fileLoc = root_dir + "\\" + img_loc[i];


    string name = img_loc[i].substr(0,img_loc[i].find("."));
    cv::VideoCapture cap(fileLoc);
    image_window win;

    int cnt = 0;


    while (!win.is_closed())
    {
        cv::Mat temp;
        cap >> temp;

        if (temp.empty())
        {
            break;
        }

        cout << "frame number ---- " << cap.get(CV_CAP_PROP_POS_FRAMES) << endl;

        cv_image<bgr_pixel> cimg(temp);

        // some image manipulations

        win.clear_overlay();
        win.set_image(cimg);

        cout << cnt << endl;

        // save some details

        cnt++;

        cout << "after cnt++ ------------ " << cnt << endl;

    }


    cout << endl << "finished with " << img_loc[i] << ", proceed to the next video?" << endl;
    cin.get();
}

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

解释这是做什么 -

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

答案 6 :(得分:1)

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

答案 7 :(得分:0)

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

答案 8 :(得分: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+_\-\.%=&amp;]*)?)?(#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)/gi

答案 9 :(得分: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

答案 10 :(得分:0)

尝试Regexy::Web::Url

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

答案 11 :(得分:0)

尽管我参加聚会很晚,但是这个简单的正则表达式肯定会在将来对某人有所帮助。此正则表达式的主要目的是用于URL拆分器,但我们也可以使用它来测试字符串中的url。

var urlMatcher = /([--:\w?%&+~#=]*\.[a-z]{2,4}\/{0,2})((?:[?&](?:\w+)=(?:\w+))+|[--:\w?@%&+~#=]+)?/g;

用法:

var string = 'stackoverflow.com';
console.log(string.match(urlMatcher) ? true : false);

如果您还需要验证电子邮件,请在第一个子句中添加“ @”,如下所示:

var urlMatcher = /([--:\w?%&+~#=]*\.[a-z]{2,4}\/{0,2})((?:[?&](?:\w+)=(?:\w+))+|[--:\w?@%&+~#=]+)?/g;
console.log('gv@test.com'.match(urlMatcher) ? true : false);

下面带有几个测试用例的完整示例:

var urls = [
            'hello world',
            'hello world @ test.com',
            'gskinner.com',
            'mobile.websightname.com',
            'foo@demo.net',
            'bar.ba@test.co.uk//',
            'www.demo.com',
            'http://foo.co.uk/',
            'http://regexr.com/foo.html?q=bar?h=lol',
            'http://www.regexr.com/3ajfi',
            'googl.travel',
            'google.in',
            '[url]google.com',
            'https://google.com'
            ];

urls.forEach(function(item){
    console.log(item + ' -- ' + (item.match(urlMatcher) ? true : false));
});

信用 Regexr url splitter

答案 12 :(得分:-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');

答案 13 :(得分:-1)

"(?<=https?://)([^/\n\s]+)(?=/|\n\b)"

应该匹配以 http:// 或 https:// 开头的任何域。这个想法是设置一个“lookbehind”和一个“lookahead”匹配 https:// 和右边第一个斜杠之间的部分。可能肯定有缺陷,但比我见过的其他表达方式简单得多。

答案 14 :(得分:-2)

(http|www)\S+

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

答案 15 :(得分:-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 with example:

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