我正在尝试编写一个正则表达式,从URI字符串中删除协议并保留主机名:
因此http://www.mysite.com
应该成为www.mysite.com
但我不确定我需要涵盖哪种类型的正则表达式http
,https
,ftp
,pop
等...
hostname = reReplace(uri, "regex to match any protocol", "")
我搞乱了一些组合,但我没有找到任何例子。
答案 0 :(得分:3)
<cfset urlstring = 'http://myhostname.site.com' />
<cfset domain = ReReplace(urlstring, '^.*?://([^/?##]+).*$', '\1', 'ONE') />
<cfoutput>#domain#</cfoutput>
这个将匹配所有协议,并提取域,无论您是否有尾随信息,如:
http://www.mysite.com/x/y
http://www.mysite.com/x?q=var
http://www.mysite.com?q=var
或只是普通的
http://www.mysite.com
答案 1 :(得分:2)
可能有点矫枉过正,但java url类有一堆方便的方法可以分割网址。
myUrl = createObject("java","java.net.URL").init("http://www.google.com:80/dir/page.html?a=aa");
myUrl.getProtocol(); // http
myUrl.getHost(); // www.google.com
myUrl.getPort(); // 80
myUrl.getPath(); // /dir/page.html
myUrl.getQuery(); // a=aa
myUrl.toExternalForm(); // http://www.google.com:80/dir/page.html?a=aa
myUrl.toString(); // http://www.google.com:80/dir/page.html?a=aa
http://download.oracle.com/javase/1.5.0/docs/api/java/net/URL.html
使用带有替换的url类可能比使用正则表达式更快。例如
str = replace( str, createObject("java","java.net.URL").init(str).getProtocol() & "://", "", "one" );
在我的快速基准测试中,看起来上面的示例执行速度比正则表达式更快。</ p>
var sys = createObject( 'java', 'java.lang.System' );
var timer1 = sys.nanoTime();
var timer2 = sys.nanoTime();
var egUrl = "http://www.google.com/dir/page.html?a=aa";
var test1 = "";
var test2 = "";
// 54784
timer1 = sys.nanoTime();
test1 = replace( egUrl, createObject("java","java.net.URL").init( egUrl ).getProtocol() & "://", "", "one" );
timer1 = sys.nanoTime() - timer1;
// 66032
timer2 = sys.nanoTime();
test2 = reReplace( egUrl, '^.*?://([^/?##]+).*$', '\1', 'ONE' );
timer2 = sys.nanoTime() - timer2;
66032us与54784us之间没有太大区别。不要忘记运行自己的基准测试。使用正则表达式可能更具可读性,即使它稍慢一点。
答案 2 :(得分:1)
您不需要费心匹配协议的所有组合,因为分隔符://
是常量,您可以在后面使用它。这将匹配://
之后的任何内容,直到第一个/
:
(?<=://)[^/]+
请注意,必须存在http://
或其他内容;否则正则表达式将无法匹配。
编辑:请注意,如果没有终止/
,您需要确保您没有使用多行正则表达式,否则匹配将转移到以下行。这很容易缓解,但可能,您传递的字符串只是一个URI。
答案 3 :(得分:1)
下面代码第二行中的正则表达式适用于列出的所有示例(这是服务器名称方案的各种排列,以及URL的各种其他部分的包含和省略:协议,路径,查询字符串元素和锚定器。
我没有对非网址中的误报或下面未列出的任何网址格式进行测试。其他人提到了mailto URL ...这需要完全不同的正则表达式,这可能超出了这个要求的范围,因此我没有包含对它的支持。
<cfflush interval="16">
<cfset sRegex = "^(?:\w+://)?([a-zA-Z0-9\.-]+)(?:(?:/|\?){0,}.*)?$">
<cfsavecontent variable="lUrls">
[protocol]://[server]/path?arg=val,
[protocol]://[server]/path?arg=val#anchor,
[protocol]://[server]/path?arg,
[protocol]://[server]/path?arg#anchor,
[protocol]://[server]/path?,
[protocol]://[server]/path?#anchor,
[protocol]://[server]/path,
[protocol]://[server]/path#anchor,
[protocol]://[server]/,
[protocol]://[server]/#anchor,
[protocol]://[server],
[protocol]://[server]#anchor,
[protocol]://[server]/?arg=val,
[protocol]://[server]/?arg=val#anchor,
[protocol]://[server]/?arg,
[protocol]://[server]/?arg#anchor,
[protocol]://[server]/?,
[protocol]://[server]/?#anchor,
[protocol]://[server]?arg=val,
[protocol]://[server]?arg=val#anchor,
[protocol]://[server]?arg,
[protocol]://[server]?arg#anchor,
[protocol]://[server]?,
[protocol]://[server]?#anchor,
[server]/path?arg=val,
[server]/path?arg=val#anchor,
[server]/path?arg,
[server]/path?arg#anchor,
[server]/path?,
[server]/path?#anchor,
[server]/path,
[server]/path#anchor,
[server]/,
[server]/#anchor,
[server],
[server]#anchor,
[server]/?arg=val,
[server]/?arg=val#anchor,
[server]/?arg,
[server]/?arg#anchor,
[server]/?,
[server]/?#anchor,
[server]?arg=val,
[server]?arg=val#anchor,
[server]?arg,
[server]?arg#anchor,
[server]?,
[server]?#anchor
</cfsavecontent>
<cfset lServers = "127.0.0.1,localhost,stackoverflow.com">
<cfloop index="sProtocol" list="http,ftp">
<cfloop index="sServer" list="#lServers#">
<cfloop index="sUrl" list="#lUrls#">
<cfset sUrl = trim(sUrl)><!--- remove CRLF --->
<cfset sUrl = replace(sUrl, "[protocol]", sProtocol)>
<cfset sUrl = replace(sUrl, "[server]", sServer)>
<cfset sServerFromUrl = reReplace(sUrl, sRegex, "\1", "ONE")>
<cfoutput>Extracted #sServerFromUrl# from #sUrl#</cfoutput>
<cfif listFind(lServers, sServerFromUrl)>
<span style="color:green">good match</span><br />
<cfelse>
<span style="color:red">BAD MATCH</span><br />
</cfif>
</cfloop>
</cfloop>
</cfloop>
答案 4 :(得分:0)
这很简单:
<cfset UrlWithoutProtocol = ReReplace( InputUrl , '^\w+://' , '' ) />
这将匹配(并删除)所有以服务器为目标的字母数字协议(即http,https,ftp等),并且不需要明确提及您想要的那些协议。
(它不匹配mailto或其他不使用/模仿//server
语法的协议。)
如果你确实想要明确,你可以简单地使用:
^(?:https?|ftp|pop|etc)://
但除非你有特定理由这样做,否则第一个更好。
答案 5 :(得分:-1)
使用起来更容易:
<cfset url_string="http://www.buyjustlocal.com">
<cfset domain = listLast(url_string,"://")>
<cfoutput>#domain#</cfoutput>