Regex для соответствия пути перед ресурсом из URL - PullRequest
4 голосов
/ 03 июня 2011

Точно так же, как все понимают используемый словарь, общая структура URL выглядит следующим образом:

  http   ://   www.a.com   /  path/to/resource.html  ?  query=value  #  fragment
{scheme} ://  {authority}  /         {path}          ?   {query}     #  {fragment}

Путь состоит из пути и ресурса, в случае path/to/resource.html путь равен path/to/, а ресурс - resource.html.

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

Проблема:

Я пытаюсь создать регулярное выражение для удаления ресурса из пути URL-адреса, что необходимо при наличии ссылки на веб-странице, которая является относительным путем. Например:

  1. Я посещаю www.domain.com/path/to/page1.html.
  2. Существует относительная ссылка на /page2.html
  3. Удалите /page1.html из URL
  4. Добавить /page2.html к www.domain.com/path/to

Результат: в www.domain.com/path/to/page2.html

Я застрял на шаге 3!

Я выделил путь и ресурс, но теперь я хочу разделить их. Регулярное выражение, которое я пытался найти, выглядит так: \z([^\/]\.[^\/])

В C # такое же регулярное выражение: "\\z([^/]\\.[^/])"

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

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

Вот несколько примеров:

/ path / to / resource.html => / path / to / и resource.html
/pa.th/to/resource.html => /pa.th/to/ и resource.html
/path/to/resource.html/ => /path/to/resource.html/
/*I#$>/78zxdc.78&(!~ => / * I # $> / и 78zxdc.78 & (! ~

Спасибо за вашу помощь!

Ответы [ 5 ]

3 голосов
/ 03 июня 2011

System.Uri

var uri = new Uri("http://www.domain.com/path/to/page1.html?query=value#fragment");

Console.WriteLine(uri.Scheme); // http
Console.WriteLine(uri.Host); // www.domain.com
Console.WriteLine(uri.AbsolutePath); // /path/to/page1.html
Console.WriteLine(uri.PathAndQuery); // /path/to/page1.html?query=value
Console.WriteLine(uri.Query); // ?query=value
Console.WriteLine(uri.Fragment); // #fragment
Console.WriteLine(uri.Segments[uri.Segments.Length - 1]); // page1.html

for (var i = 0 ; i < uri.Segments.Length ; i++)
{
    Console.WriteLine("{0}: {1}", i, uri.Segments[i]);
    /*
    Output
    0: /
    1: path/
    2: to/
    3: page1.html
    */
}
2 голосов
/ 03 июня 2011

Я не могу представить, почему вы захотите использовать для этого регулярные выражения, когда класс Uri уже почти всю работу за вас выполняет.И чтобы получить финальную часть (т.е. отделить ресурс от пути), вы можете просто использовать String.LastIndexOf и String.Substring.Например:

Uri myUri;
if (!Uri.TryCreate(linkString, UriKind.RelativeOrAbsolute, out myUri))
{
    // some kind of error.
}
int pos = myUri.AbsolutePath.LastIndexOf('/');
++pos;
string resource = myUri.AbsolutePath.Substring(pos);    

У меня мало сомнений, что вы можете делать это с помощью регулярного выражения.Хотя я сомневаюсь, что это победа.Как вы сказали, URL-адреса, которые вы находите при сканировании в Интернете, могут быть довольно плохими.Мой сканер тратит немало усилий, чтобы нормализовать некоторые действительно дико выглядящие ссылки.Я регулярно сталкиваюсь с такими вещами, как http://example.com/dir/subdir/subsubdir/../../dir///moretrash/resource.html.И вы не поверите (или, может быть, если вы будете ползать по сети), странное спасение, которое я вижу.Класс Uri хорошо разбирает URL, чтобы я мог его нормализовать.Unescaping - это то, что вы просто не можете сделать с помощью регулярного выражения.

Мой опыт показывает, что время создания экземпляра Uri сокращается по сравнению с временем, необходимым для нормализации URL: unescape, фрагменты фрагментови идентификаторы сеанса, идентифицируйте и избегайте прокси и ловушек гусеничного устройства, удаляйте посторонние косые черты и навигацию по пути (например, /./ и /../) и т. д. Я просто не вижу, где использовать регулярное выражение, даже если оно было быстрее1015 * улучшит мое время выполнения.И я серьезно сомневаюсь, что он может так же хорошо, как Uri.TryCreate, анализировать URL-адреса, которые я нахожу в дикой природе.

1 голос
/ 03 июня 2011

Я думаю, что, возможно, вам следует разбить строку на '/', а не зацикливаться на предложении регулярного выражения. также вы смотрели на http://msdn.microsoft.com/en-us/library/ms952653.aspx

1 голос
/ 03 июня 2011

Поддерживает ли ваш движок регулярных выражений прогнозирование переменной длины?Если это так, вы можете использовать это, чтобы смотреть вперед (следовательно, исключая) символы без косой черты в конце:

.*/(?=[^/]*$)

В качестве альтернативы используйте группы захвата, и путь будет группа 1 , ресурс группа 2 :

(.*/)([^/]*$)

Алгоритм без регулярных выражений будет выглядеть так:

  1. Сохранение pos последней косой черты
  2. Substr от 0 с длиной pos+1

Примечание : я намеренно проигнорировал . здесь.Какое значение они имеют?В HTML, если у вас есть путь, который не заканчивается косой чертой, относительные пути будут относительно родительского элемента последней части .Таким образом, для целей этого обсуждения часть без точек в основном является ресурсом без расширения.

1 голос
/ 03 июня 2011

Чтобы извлечь часть ресурса URI, вы можете использовать:

^                  # matches start of str
.*                 # greedy match up to the last '/'
\/                 # literal '/'
(                  # start capture of resource part
   [^\/\?\#]*      # zero or more chars except '/', '?', and '#'
)                  # end capture
(?:                # start optional group - query part
  \?               # literal '?' for optional query
  .+?              # non-greedy match for any chars
)?                 # end of optional group
(?:                # start of optional group - fragment part
  \#               # literal '#' for optional fragment
  .+?              # non-greedy match for any chars
)?                 # end of optional group
$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...