regex - 正则表达式特殊字符 - 正则表达式空格



获取URL的部分(正则表达式) (18)

鉴于URL(单行):
http://test.example.com/dir/subdir/file.html

我如何使用正则表达式提取以下部分:

  1. 子域(测试)
  2. 域(example.com)
  3. 没有文件的路径(/ dir / subdir /)
  4. 该文件(file.html)
  5. 文件路径(/dir/subdir/file.html)
  6. 没有路径的网址( http://test.example.com
  7. (添加其他你认为会有用的东西)

即使输入以下URL,正则表达式也应该正常工作:
http://example.example.com/example/example/example.html

谢谢。


Answer #1

一个正则表达式来解析和分解完整的URL,包括查询参数和锚点,例如

https://www.google.com/dir/1/2/search.html?arg=0-a&arg1=1-b&arg3-c#hash

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$

RexEx职位:

网址:RegExp ['$&'],

协议:正则表达式$ 2,

主持人:正则表达式$ 3

路径:正则表达式$ 4

文件:正则表达式$ 6

查询:正则表达式$ 7,

哈希:正则表达式$ 8

那么你可以很容易地进一步解析主机('。'分隔)。

会做的是使用这样的东西:

/*
    ^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$
*/
proto $1
host $2
port $3
the-rest $4

进一步解析“其余”尽可能具体。 在一个正则表达式中这样做有点疯狂。



Answer #3

使用http://www.fileformat.info/tool/regex.htm hometoast的正则表达式工作得很好。

但是,这是一笔交易,我想在我的程序的不同情况下使用不同的正则表达式模式。

例如,我有这个URL,并且有一个枚举,它列出了我的程序中所有支持的URL。 枚举中的每个对象都有一个getRegexPattern方法,该方法返回正则表达式模式,然后将其用于与URL进行比较。 如果特定的正则表达式模式返回true,那么我知道这个URL是我的程序支持的。 因此,每个枚举都有它自己的正则表达式,具体取决于它应该在URL内部看到的位置。

Hometoast的建议是伟大的,但在我的情况下,我认为这将无济于事(除非我复制在所有枚举中粘贴相同的正则表达式)。

这就是为什么我想让答案分别为每种情况提供正则表达式的原因。 虽然家庭托付+1。 ;)


Answer #4

可悲的是,这不适用于某些网址。 举个例子,这个: http://www.example.org/&value=329 : http://www.example.org/&value=329

价值= 329也没有

甚至根本没有参数(一个简单的URL)!

我明白,正则表达式期望一些严重复杂/长的URL,但它也应该能够在简单的URL上工作,对吗?



Answer #6

建议一个更可读的解决方案(在Python中,但适用于任何正则表达式):

def url_path_to_dict(path):
    pattern = (r'^'
               r'((?P<schema>.+?)://)?'
               r'((?P<user>.+?)(:(?P<password>.*?))[email protected])?'
               r'(?P<host>.*?)'
               r'(:(?P<port>\d+?))?'
               r'(?P<path>/.*?)?'
               r'(?P<query>[?].*?)?'
               r'$'
               )
    regex = re.compile(pattern)
    m = regex.match(path)
    d = m.groupdict() if m is not None else None

    return d

def main():
    print url_path_to_dict('http://example.example.com/example/example/example.html')

打印:

{
'host': 'example.example.com', 
'user': None, 
'path': '/example/example/example.html', 
'query': None, 
'password': None, 
'port': None, 
'schema': 'http'
}


Answer #8

我发现最高的投票答案(hometoast的答案)对我来说并不完美。 两个问题:

  1. 它不能处理端口号。
  2. 散列部分被破坏。

以下是修改后的版本:

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$

部件位置如下:

int SCHEMA = 2, DOMAIN = 3, PORT = 5, PATH = 6, FILE = 8, QUERYSTRING = 9, HASH = 12

匿名用户发布的修改:

function getFileName(path) {
    return path.match(/^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/[\w\/-]+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$/i)[8];
}

Answer #9

我尝试了其中的一些内容,这些内容并未覆盖我的需求,特别是最高的投票,它没有找到没有路径的网址( http://example.com/

也缺乏团体名称使其无法使用(或者我的jinja2技能缺乏)。

所以这是我的版本稍微修改,源代码是这里最高的投票版本:

^((?P<protocol>http[s]?|ftp):\/)?\/?(?P<host>[^:\/\s]+)(?P<path>((\/\w+)*\/)([\w\-\.]+[^#?\s]+))*(.*)?(#[\w\-]+)?$

Answer #10

我意识到我迟到了,但是有一个简单的方法可以让浏览器为你解析一个没有正则表达式的url:

var a = document.createElement('a');
a.href = 'http://www.example.com:123/foo/bar.html?fox=trot#foo';

['href','protocol','host','hostname','port','pathname','search','hash'].forEach(function(k) {
    console.log(k+':', a[k]);
});

/*//Output:
href: http://www.example.com:123/foo/bar.html?fox=trot#foo
protocol: http:
host: www.example.com:123
hostname: www.example.com
port: 123
pathname: /foo/bar.html
search: ?fox=trot
hash: #foo
*/

Answer #11

我知道你在这方面声称与语言无关,但是你能告诉我们你使用的是什么,所以我们知道你有什么正则表达式的能力?

如果您具有非捕获匹配的功能,则可以修改hometoast的表达式,以便您不想捕获的子表达式如下设置:

(?:SOMESTUFF)

你仍然需要将正则表达式复制粘贴(并稍微修改)到多个位置,但这是有道理的 - 你不只是检查子表达式是否存在,而是作为URL的一部分存在。 对子表达使用非捕捉修饰符可以为您提供您所需要的内容,而无需其他任何东西,如果我正确阅读您的内容,就是您想要的内容。

就像一个小小的便条一样,hometoast的表达式不需要在'https'的括号内加上括号,因为他只有一个字符。 量词量化直接在它们之前的一个字符(或字符类或子表达式)。 所以:

https?

会匹配'http'或'https'就好了。


Answer #12

我试图在javascript中解决这个问题,应该通过以下方式来处理:

var url = new URL('http://a:[email protected]:890/path/[email protected]/foo.js?foo=bar&bingobang=&[email protected]#foobar/bing/[email protected]?bang');

因为(至少在Chrome中)它解析为:

{
  "hash": "#foobar/bing/[email protected]?bang",
  "search": "?foo=bar&bingobang=&[email protected]",
  "pathname": "/path/[email protected]/foo.js",
  "port": "890",
  "hostname": "example.com",
  "host": "example.com:890",
  "password": "b",
  "username": "a",
  "protocol": "http:",
  "origin": "http://example.com:890",
  "href": "http://a:[email protected]:890/path/[email protected]/foo.js?foo=bar&bingobang=&[email protected]#foobar/bing/[email protected]?bang"
}

但是,这不是跨浏览器( https://developer.mozilla.org/en-US/docs/Web/API/URL ),所以我拼凑在一起把相同的部分拉出如上:

^(?:(?:(([^:\/#\?]+:)?(?:(?:\/\/)(?:(?:(?:([^:@\/#\?]+)(?:\:([^:@\/#\?]*))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((?:\/?(?:[^\/\?#]+\/+)*)(?:[^\?#]*)))?(\?[^#]+)?)(#.*)?

信用这个正则表达式去https://gist.github.com/rpflorence发布这个jsperf http://jsperf.com/url-parsing (最初在这里找到: https://gist.github.com/jlong/2428561#comment-310066 ://gist.github.com/jlong​​/2428561 https://gist.github.com/jlong/2428561#comment-310066 )谁提出了正式的正则表达式。

部件按此顺序排列:

var keys = [
    "href",                    // http://user:[email protected]:81/directory/file.ext?query=1#anchor
    "origin",                  // http://user:[email protected]:81
    "protocol",                // http:
    "username",                // user
    "password",                // pass
    "host",                    // host.com:81
    "hostname",                // host.com
    "port",                    // 81
    "pathname",                // /directory/file.ext
    "search",                  // ?query=1
    "hash"                     // #anchor
];

还有一个小型图书馆,它包装它并提供查询参数:

https://github.com/sadams/lite-url (也可用于凉亭)

如果您有改进之处,请创建更多测试的拉取请求,我会接受并合并谢谢。


Answer #13

执行完整解析的正则表达式非常可怕。 我已经包含了可读性的命名反向引用,并将每个部分分成不同的行,但它仍然是这样的:

^(?:(?P<protocol>\w+(?=:\/\/))(?::\/\/))?
(?:(?P<host>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::(?P<port>[0-9]+))?)\/)?
(?:(?P<path>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)?
(?P<file>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)
(?:\?(?P<querystring>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))?
(?:#(?P<fragment>.*))?$

需要这么详细的事情是,除了协议或端口外,任何部分都可以包含HTML实体,这使得片段的描述非常棘手。 所以在最后几种情况下 - 主机,路径,文件,查询字符串和片段,我们允许任何html实体或任何不是?# 。 一个html实体的正则表达式如下所示:

$htmlentity = "&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);"

当提取出来的时候(我用胡子语法来表示它),它变得更清晰一些:

^(?:(?P<protocol>(?:ht|f)tps?|\w+(?=:\/\/))(?::\/\/))?
(?:(?P<host>(?:{{htmlentity}}|[^\/?#:])+(?::(?P<port>[0-9]+))?)\/)?
(?:(?P<path>(?:{{htmlentity}}|[^?#])+)\/)?
(?P<file>(?:{{htmlentity}}|[^?#])+)
(?:\?(?P<querystring>(?:{{htmlentity}};|[^#])+))?
(?:#(?P<fragment>.*))?$

在JavaScript中,当然,你不能使用命名的反向引用,所以正则表达式就变成了

^(?:(\w+(?=:\/\/))(?::\/\/))?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::([0-9]+))?)\/)?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)(?:\?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))?(?:#(.*))?$

并且在每个匹配中,协议是\1 ,主机是\2 ,端口是\3 ,路径\4 ,文件\5 ,查询字符串\6和片段\7


Answer #14

正则表达式来获取没有文件的URL路径。

url =' http://domain/dir1/dir2/somefile (/ ^(http:// [^ /] +)((?:/ [^ /] +)+(?= /)) ?/(?:[^ /] +)?$ / I).to_s

它可以用于添加一个相对路径到这个URL。


Answer #15

这个改进的版本应该像解析器一样可靠地工作。

   // Applies to URI, not just URL or URN:
   //    http://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Relationship_to_URL_and_URN
   //
   // http://labs.apache.org/webarch/uri/rfc/rfc3986.html#regexp
   //
   // (?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?
   //
   // http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax
   //
   // [email protected] matches the entire uri
   // $1 matches scheme (ftp, http, mailto, mshelp, ymsgr, etc)
   // $2 matches authority (host, user:[email protected], etc)
   // $3 matches path
   // $4 matches query (http GET REST api, etc)
   // $5 matches fragment (html anchor, etc)
   //
   // Match specific schemes, non-optional authority, disallow white-space so can delimit in text, and allow 'www.' w/o scheme
   // Note the schemes must match ^[^\s|:/?#]+(?:\|[^\s|:/?#]+)*$
   //
   // (?:()(www\.[^\s/?#]+\.[^\s/?#]+)|(schemes)://([^\s/?#]*))([^\s?#]*)(?:\?([^\s#]*))?(#(\S*))?
   //
   // Validate the authority with an orthogonal RegExp, so the RegExp above won’t fail to match any valid urls.
   function uriRegExp( flags, schemes/* = null*/, noSubMatches/* = false*/ )
   {
      if( !schemes )
         schemes = '[^\\s:\/?#]+'
      else if( !RegExp( /^[^\s|:\/?#]+(?:\|[^\s|:\/?#]+)*$/ ).test( schemes ) )
         throw TypeError( 'expected URI schemes' )
      return noSubMatches ? new RegExp( '(?:www\\.[^\\s/?#]+\\.[^\\s/?#]+|' + schemes + '://[^\\s/?#]*)[^\\s?#]*(?:\\?[^\\s#]*)?(?:#\\S*)?', flags ) :
         new RegExp( '(?:()(www\\.[^\\s/?#]+\\.[^\\s/?#]+)|(' + schemes + ')://([^\\s/?#]*))([^\\s?#]*)(?:\\?([^\\s#]*))?(?:#(\\S*))?', flags )
   }

   // http://en.wikipedia.org/wiki/URI_scheme#Official_IANA-registered_schemes
   function uriSchemesRegExp()
   {
      return 'about|callto|ftp|gtalk|http|https|irc|ircs|javascript|mailto|mshelp|sftp|ssh|steam|tel|view-source|ymsgr'
   }

Answer #16

这是一个完整的,不依赖任何协议。

function getServerURL(url) {
        var m = url.match("(^(?:(?:.*?)?//)?[^/?#;]*)");
        console.log(m[1]) // Remove this
        return m[1];
    }

getServerURL("http://dev.test.se")
getServerURL("http://dev.test.se/")
getServerURL("//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js")
getServerURL("//")
getServerURL("www.dev.test.se/sdas/dsads")
getServerURL("www.dev.test.se/")
getServerURL("www.dev.test.se?abc=32")
getServerURL("www.dev.test.se#abc")
getServerURL("//dev.test.se?sads")
getServerURL("http://www.dev.test.se#321")
getServerURL("http://localhost:8080/sads")
getServerURL("https://localhost:8080?sdsa")

打印

http://dev.test.se

http://dev.test.se

//ajax.googleapis.com

//

www.dev.test.se

www.dev.test.se

www.dev.test.se

www.dev.test.se

//dev.test.se

http://www.dev.test.se

http://localhost:8080

https://localhost:8080

Answer #17
/^((?P<scheme>https?|ftp):\/)?\/?((?P<username>.*?)(:(?P<password>.*?)|)@)?(?P<hostname>[^:\/\s]+)(?P<port>:([^\/]*))?(?P<path>(\/\w+)*\/)(?P<filename>[-\w.]+[^#?\s]*)?(?P<query>\?([^#]*))?(?P<fragment>#(.*))?$/

从我对类似问题的回答 。 比其他人提到的更好,因为他们有一些bug(比如不支持用户名/密码,不支持单字符文件名,碎片标识符被破坏)。


Answer #18
String s = "https://www.thomas-bayer.com/axis2/services/BLZService?wsdl";

String regex = "(^http.?://)(.*?)([/\\?]{1,})(.*)";

System.out.println("1: " + s.replaceAll(regex, "$1"));
System.out.println("2: " + s.replaceAll(regex, "$2"));
System.out.println("3: " + s.replaceAll(regex, "$3"));
System.out.println("4: " + s.replaceAll(regex, "$4"));

将提供以下输出:
1:https://
2:www.thomas-bayer.com
3:/
4:axis2 / services / BLZService?wsdl

如果您将URL更改为
String s =“ https://www.thomas-bayer.com?wsdl=qwerwer&ttt=888 ”; 输出结果如下:
1:https://
2:www.thomas-bayer.com
3:?
4:wsdl = qwerwer&ttt = 888

请享用..
Yosi列弗





url