#regex #coldfusion #coldfusion-9
#регулярное выражение #coldfusion #coldfusion-9
Вопрос:
Я пытаюсь написать регулярное выражение, которое исключает протокол из строки URI и оставляет имя хоста:
Так http://www.mysite.com
должно стать www.mysite.com
Но я не уверен, какой тип регулярного выражения мне нужно охватить http
, https
, ftp
, pop
и т.д…
hostname = reReplace(uri, "regex to match any protocol", "")
Я повозился с некоторыми комбинациями, но не нашел ни одного примера.
Комментарии:
1. Приведенные ниже различные ответы действуют немного по-разному — какой из них вы хотите, зависит от того, содержат ли ваши входные URL-адреса больше, чем имя хоста, и если да, нужно ли вам это удалить — вы должны добавить эту информацию в вопрос.
Ответ №1:
<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. Шон, извини: понижение голоса, потому что ваше регулярное выражение не работает (для меня, на CF9, используя ваш собственный код) для второго и третьего ваших собственных примеров! Вы проверили свой ответ перед публикацией?
2. Мне нравится, когда я тестировал код, а затем он запускается … и, по-видимому, все еще не протестирован.
3. @AdamCameron хороший улов, я отредактировал и опубликовал новый шаблон. Думал, что я правильно протестировал первый … увы.
Ответ №2:
Может быть излишним, но класс 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() amp; "://", "", "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() amp; "://", "", "one" );
timer1 = sys.nanoTime() - timer1;
// 66032
timer2 = sys.nanoTime();
test2 = reReplace( egUrl, '^.*?://([^/?##] ).*$', '1', 'ONE' );
timer2 = sys.nanoTime() - timer2;
Нет большой разницы между 66032us и 54784us. Не забудьте запустить свои собственные тесты. Может быть удобнее использовать регулярное выражение, даже если оно немного медленнее.
Ответ №3:
Вам не нужно беспокоиться о сопоставлении всех комбинаций протокола, потому что разделитель ://
является константой, и вы можете использовать это при просмотре. Это будет соответствовать чему угодно после ://
вплоть до первого /
:
(?<=://)[^/]
Обратите внимание, что http://
или что угодно должно присутствовать; в противном случае регулярное выражение ничему не будет соответствовать.
Редактировать: Обратите внимание, что если нет завершения /
, вам нужно убедиться, что вы не выполняете многострочное регулярное выражение, иначе совпадение перейдет на следующие строки. Это достаточно легко смягчить, но, предположительно, строка, которую вы будете передавать, будет просто одним URI.
Комментарии:
1. Если ваше намерение состоит в том, чтобы соответствовать только домену,
[^/]
этого недостаточно — вы хотите,[^/?#]
потому что в противном случаеhttp://domain.com?this#that
было бы полностью сопоставлено, в то время какhttp://domain.com/?this#that
было бы предоставлено только домен.2. Кроме того, регулярным выражением по умолчанию в ColdFusion является Apache ORO, который не поддерживает поисковые запросы. Если делать это таким образом, Ди нужно будет использовать библиотеку регулярных выражений Java вместо этого.
3. Достаточно справедливо 🙂 Ничего не знаю о ColdFushion, только регулярное выражение
Ответ №4:
Регулярное выражение во второй строке кода ниже работает для всех перечисленных примеров (которые представляют собой различные перестановки схем имен серверов, а также включение и исключение различных других частей 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>
Ответ №5:
Это довольно просто:
<cfset UrlWithoutProtocol = ReReplace( InputUrl , '^w ://' , '' ) />
Это сопоставит (и удалит) все буквенно-цифровые протоколы, предназначенные для сервера (например, http, https, ftp и т.д.), И не требует явного указания тех, которые вы хотите.
(Это не будет соответствовать mailto или другим протоколам, которые не используют / имитируют //server
синтаксис.)
Если вы хотите быть явным, вы могли бы просто использовать:
^(?:https?|ftp|pop|etc)://
Но если у вас нет конкретной причины делать это таким образом, первое лучше.
Комментарии:
1. Майкл, опубликованный пример работает на Railo, и это довольно просто, поэтому я не вижу ничего плохого. Чтобы было понятно, содержимое
InputUrl
должно быть одним URL (не работает для встроенных / множественных) и не должно содержать никаких символов, отличных от URL (пробелов / кавычек / и т.д.) В начале. Если есть какая-то другая проблема, вам нужно будет четко указать, что вы видите и чего ожидаете.
Ответ №6:
Это проще просто использовать:
<cfset url_string="http://www.buyjustlocal.com">
<cfset domain = listLast(url_string,"://")>
<cfoutput>#domain#</cfoutput>
Комментарии:
1. Это не проще, потому что это не работает. Рассмотрите URI
http://en.wikipedia.org/wiki/Special:Watchlist
— ваш код вернетWatchlist
для домена.2. Верно.
ListRest
вероятно, это то, что вы искали здесь.3. Ни ListLast, ни ListRest не работают с разделителями из нескольких символов. Вы могли бы использовать
ListRest(url_string,'/')
— это удалило бы протокол и // префикс (при сохранении пути), но это также повредило бы URL, в котором отсутствовал протокол, в отличие от того,url_string.replaceAll('^w ://','')
что этого не делает.