Regex для разделения строки URI на части протокола и имени хоста - PullRequest
2 голосов
/ 04 ноября 2011

Я пытаюсь написать регулярное выражение, которое исключает протокол из строки URI и оставляет имя хоста:

Так что http://www.mysite.com должно стать www.mysite.com

Но я неуверен, какой тип регулярных выражений мне нужно охватить http, https, ftp, pop и т. д.комбо, но я не нашел примеров.

Ответы [ 6 ]

3 голосов
/ 04 ноября 2011
<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
2 голосов
/ 18 ноября 2011

Может быть излишним, но у класса java url есть несколько удобных методов для разделения 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" );

В моих быстрых тестах кажется, что приведенный выше пример выполняется быстрее, чем замена регулярного выражения.

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. Не забудьте запустить свои собственные тесты. Возможно, будет удобнее читать регулярные выражения, даже если это немного медленнее.

1 голос
/ 05 ноября 2011

Регулярное выражение во второй строке приведенного ниже кода работает для всех перечисленных примеров (которые представляют собой различные варианты схем имен серверов, а также включение и пропуск различных других частей URL-адреса: протокола, пути, элементов строки запроса и якоря.

Я не проверял его на наличие ложных срабатываний в URL-адресах или на шаблонах URL, не указанных ниже. Кто-то еще упомянул URL-адреса mailto ..., для которых потребовалось бы совершенно другое регулярное выражение, что может выходить за рамки этого требования, поэтому я не включил его поддержку.

<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>
1 голос
/ 04 ноября 2011

Вам не нужно беспокоиться о сопоставлении всех комбинаций протокола, потому что разделитель :// является константой, и вы можете использовать это в прошлом.Это будет соответствовать чему-либо после :// вплоть до первого /:

(?<=://)[^/]+

Обратите внимание, что http:// или что-то еще должно присутствовать;в противном случае регулярное выражение не будет соответствовать чему-либо.

Редактировать: обратите внимание, что если нет завершающего /, вам нужно убедиться, что вы не выполняете многострочное регулярное выражение, иначе совпадение будет перенесено на следующие строки,Это достаточно легко устранить, но, по-видимому, передаваемая вами строка будет просто одним URI.

0 голосов
/ 02 сентября 2012

Просто использовать:

<cfset url_string="http://www.buyjustlocal.com">
<cfset domain = listLast(url_string,"://")>
<cfoutput>#domain#</cfoutput>
0 голосов
/ 04 ноября 2011

Все довольно просто:

<cfset UrlWithoutProtocol = ReReplace( InputUrl , '^\w+://' , '' ) />

Это будет соответствовать (и удалять) всем буквенно-цифровым протоколам, которые нацелены на сервер (то есть http, https, ftp и т. Д.), И не требует явного упоминания тех, которые вы хотите.
(Не соответствует mailto или другим протоколам, которые не используют / не имитируют синтаксис //server.)

Если вы хотите быть явным, вы можете просто использовать:

^(?:https?|ftp|pop|etc)://

Но если у вас нет конкретной причины сделать это таким образом, первое лучше.

...