如何检查给定的字符串是否是有效的URL地址?

我对正则表达式的知识是基本的,不允许我从我已经在网上看到的数百个正则表达式中进行选择。


当前回答

我创建了一个类似于RFC3987和其他RFC文档提供的@eyelidlessness的正则表达式(PCRE)。@eyelidlessness和我的正则表达式之间的主要区别主要是可读性和URN支持。

下面的正则表达式是一个整体(而不是与PHP混合),所以它可以很容易地用于不同的语言(只要它们支持PCRE)

测试这个正则表达式最简单的方法是使用regex101,并使用适当的修饰符(gmx)复制粘贴下面的代码和测试字符串。

要在PHP中使用这个正则表达式,请将下面的正则表达式插入到以下代码中:

$regex = <<<'EOD'
// Put the regex here
EOD;

可以通过以下方式匹配不带方案的链路: 要匹配一个没有方案的链接(例如john.doe@gmail.com或www.google.com/pathtofile.php?query),替换此部分:

  (?:
    (?<scheme>
      (?<urn>urn)|
      (?&d_scheme)
    )
    :
  )?

用这个:

  (?:
    (?<scheme>
      (?<urn>urn)|
      (?&d_scheme)
    )
    :
  )?

但是请注意,通过替换它,regex并不是100%可靠。 使用gmx修饰符的Regex (PCRE)用于下面的多行测试字符串

(?(DEFINE)
  # Definitions
  (?<ALPHA>[\p{L}])
  (?<DIGIT>[0-9])
  (?<HEX>[0-9a-fA-F])
  (?<NCCHAR>
    (?&UNRESERVED)|
    (?&PCT_ENCODED)|
    (?&SUB_DELIMS)|
    @
  )
  (?<PCHAR>
    (?&UNRESERVED)|
    (?&PCT_ENCODED)|
    (?&SUB_DELIMS)|
    :|
    @|
    \/
  )
  (?<UCHAR>
    (?&UNRESERVED)|
    (?&PCT_ENCODED)|
    (?&SUB_DELIMS)|
    :
  )
  (?<RCHAR>
    (?&UNRESERVED)|
    (?&PCT_ENCODED)|
    (?&SUB_DELIMS)
  )
  (?<PCT_ENCODED>%(?&HEX){2})
  (?<UNRESERVED>
    ((?&ALPHA)|(?&DIGIT)|[-._~])
  )
  (?<RESERVED>(?&GEN_DELIMS)|(?&SUB_DELIMS))
  (?<GEN_DELIMS>[:\/?#\[\]@])
  (?<SUB_DELIMS>[!$&'()*+,;=])
  # URI Parts
  (?<d_scheme>
    (?!urn)
    (?:
      (?&ALPHA)
      ((?&ALPHA)|(?&DIGIT)|[+-.])*
      (?=:)
    )
  )
  (?<d_hier_part_slashes>
    (\/{2})?
  )
  (?<d_authority>(?&d_userinfo)?)
  (?<d_userinfo>(?&UCHAR)*)
  (?<d_ipv6>
    (?![^:]*::[^:]*::[^:]*)
    (
      (
        ((?&HEX){0,4})
        :
      ){1,7}
      ((?&d_ipv4)|:|(?&HEX){1,4})
    )
  )
  (?<d_ipv4>
    ((?&octet)\.){3}
    (?&octet)
  )
  (?<octet>
    (
      25[]0-5]|
      2[0-4](?&DIGIT)|
      1(?&DIGIT){2}|
      [1-9](?&DIGIT)|
      (?&DIGIT)
    )
  )
  (?<d_reg_name>(?&RCHAR)*)
  (?<d_urn_name>(?&UCHAR)*)
  (?<d_port>(?&DIGIT)*)
  (?<d_path>
    (
      \/
      ((?&PCHAR)*)*
      (?=\?|\#|$)
    )
  )
  (?<d_query>
    (
      ((?&PCHAR)|\/|\?)*
    )?
  )
  (?<d_fragment>
    (
      ((?&PCHAR)|\/|\?)*
    )?
  )
)
^
(?<link>
  (?:
    (?<scheme>
      (?<urn>urn)|
      (?&d_scheme)
    )
    :
  )
  (?(urn)
    (?:
      (?<namespace_identifier>[0-9a-zA-Z\-]+)
      :
      (?<namespace_specific_string>(?&d_urn_name)+)
    )
    |
    (?<hier_part>
      (?<slashes>(?&d_hier_part_slashes))
      (?<authority>
        (?:
          (?<userinfo>(?&d_authority))
          @
        )?
        (?<host>
          (?<ipv4>\[?(?&d_ipv4)\]?)|
          (?<ipv6>\[(?&d_ipv6)\])|
          (?<domain>(?&d_reg_name))
        )
        (?:
          :
          (?<port>(?&d_port))
        )?
      )
      (?<path>(?&d_path))?
    )
    (?:
      \?
      (?<query>(?&d_query))
    )?
    (?:
      \#
      (?<fragment>(?&d_fragment))
    )?
  )
)
$

测试字符串

# Valid URIs
ftp://cnn.example.com&story=breaking_news@10.0.0.1/top_story.htm
ftp://ftp.is.co.za/rfc/rfc1808.txt
http://www.ietf.org/rfc/rfc2396.txt
ldap://[2001:db8::7]/c=GB?objectClass?one
mailto:John.Doe@example.com
news:comp.infosystems.www.servers.unix
tel:+1-816-555-1212
telnet://192.0.2.16:80/
urn:isbn:0451450523
urn:oid:2.16.840
urn:isan:0000-0000-9E59-0000-O-0000-0000-2
urn:oasis:names:specification:docbook:dtd:xml:4.1.2
http://localhost/test/somefile.php?query=someval&variable=value#fragment
http://[2001:db8:a0b:12f0::1]/test
ftp://username:password@domain.com/path/to/file/somefile.html?queryVariable=value#fragment
https://subdomain.domain.com/path/to/file.php?query=value#fragment
https://subdomain.example.com/path/to/file.php?query=value#fragment
mailto:john.smith(comment)@example.com
mailto:user@[2001:DB8::1]
mailto:user@[255:192:168:1]
mailto:M.Handley@cs.ucl.ac.uk
http://localhost:4433/path/to/file?query#fragment
# Note that the example below IS a valid as it does follow RFC standards
localhost:4433/path/to/file

# These work with the optional scheme group although I'd suggest making the scheme mandatory as misinterpretations can occur
john.doe@gmail.com
www.google.com/pathtofile.php?query
[192a:123::192.168.1.1]:80/path/to/file.html?query#fragment

其他回答

下面是针对这种情况的最佳和最匹配的正则表达式

^(?:http(?:s)?:\/\/)?(?:www\.)?(?:[\w-]*)\.\w{2,}$
^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$

现场演示:https://regex101.com/r/HUNasA/2

我已经测试了各种表达式来满足我的要求。

作为用户,我可以用以下字符串点击浏览器搜索栏:

有效的网址

https://www.google.com http://www.google.com http://google.com/ https://google.com/ www.google.com google.com https://www.google.com.ua http://www.google.com.ua http://google.com.ua https://google.com.ua/ www.google.com.ua google.com.ua https://mail.google.com http://mail.google.com mail.google.com

无效的url

http://google https://google.c 谷歌 谷歌。 .google .google.com goole.c ...

我刚刚写了一篇博客文章,介绍了一个很好的解决方案,可以识别大多数常用格式的url,比如:

www.google.com http://www.google.com mailto: somebody@google.com somebody@google.com url www.url-with-querystring.com/ ? = has-querystring

使用的正则表达式是:

/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/
/^(http|HTTP)+(s|S)?:\/\/[\w.-]+(?:\.[\w\.-]+)+[\w\-\._\$\(\)/]+$/g

使用测试检查演示:

https://regexr.com/5cedu

下面的RegEx可以工作:

"@((((ht)|(f))tp[s]?://)|(www\.))([a-z][-a-z0-9]+\.)?([a-z][-a-z0-9]+\.)?[a-z][-a-z0-9]+\.[a-z]+[/]?[a-z0-9._\/~#&=;%+?-]*@si"