Усовершенствованный Regex: Умное автоматическое опознавание и URL замены с тегами привязки

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

Его работы регулярного выражения, но потребности дополнительный код после того, как обнаружение сделано.

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

1   (?\()?
2   (?http(?s)?://)?
3   (?
4       (?(scheme)
5           (?:www\.)?
6           |
7           www\.
8       )
9       [a-z0-9]
10      (?(outer)
11          [-a-z0-9/+&@#/%?=~_()|!:,.;čšžćđ]+(?=\))
12          |
13          [-a-z0-9/+&@#/%?=~_()|!:,.;čšžćđ]+
14      )
15  )
16  (?(?(outer)\)))

Как можно видеть, я использую названные группы получения (используемый позже в Regex.Replace()) и я также включал некоторые локальные символы (čšžćđ), которые позволяют нашим локализованным URL быть проанализированными также. Можно легко опустить их, если Вы хотели бы.

Так или иначе. Вот то, что это делает (относящийся к номерам строки):

  • 1 - обнаруживает, если URL запускается с открытых фигурных скобок (содержится в фигурных скобках), и хранит его во "внешней" именованной группе получения
  • 2 - проверки, если это запускается со схемы URL, также обнаруживающей, является ли схемой SSL или нет
  • 3 - начните анализировать сам URL (сохранит его в "URL", названном группой получения),
  • 4-8 - if оператор, который говорит: если "sheme" присутствовал затем www., часть является дополнительной, в других отношениях обязательной, чтобы строка была ссылкой (таким образом, это регулярное выражение обнаруживает все строки, которые запускаются или с http или с www),
  • 9 - первый символ после http:// или www. должна быть или буква или число (это может быть расширено, если требуется покрыть еще больше ссылок, но я решил не к тому, потому что я не могу думать о ссылке, которая запустилась бы с некоторого неясного символа),
  • 10-14 - if оператор, который говорит: если "внешний" (фигурные скобки) присутствовал, получают, все до последних закрывающих фигурных скобок иначе получает все
  • 15 - закрывает именованную группу получения для URL
  • 16 - если открытые фигурные скобки присутствовали, закрывающие фигурные скобки получения также и хранят его в "окончании" именованной группы получения

Первая и последняя строка раньше имела \s* в них также, таким образом, пользователь мог также записать открытые фигурные скобки и вставить пространство прежде, чем вставить ссылку.

Так или иначе. Мой код, который действительно связывает замену с фактическими элементами HTML привязки, точно походит на это:

value = Regex.Replace(
    value,
    @"(?\()?(?http(?s)?://)?(?(?(scheme)(?:www\.)?|www\.)[a-z0-9](?(outer)[-a-z0-9/+&@#/%?=~_()|!:,.;čšžćđ]+(?=\))|[-a-z0-9/+&@#/%?=~_()|!:,.;čšžćđ]+))(?(?(outer)\)))",
    "${outer}http${secure}://${url}${ending}",
    RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

Поскольку Вы видите, что я использую названные группы получения для замены ссылки с Тегом привязки:

"${outer}http${secure}://${url}${ending}"

Я мог также опустить http (s) часть в дисплее привязки, чтобы заставить ссылки выглядеть более дружественными, но на данный момент я решил не к.

Вопрос

Я хотел бы, чтобы мои ссылки были заменены сокращениями также. Таким образом, когда пользователь копирует очень длинную ссылку (например, если они скопировали бы ссылку с карт Google, которая обычно генерирует длинные ссылки), я хотел бы сократить видимую часть тега привязки. Ссылка работала бы, но видимая часть тега привязки будет сокращена к некоторому количеству символов. Я мог также добавить замещающий знак в конце вообще возможного (и сделать вещи еще более прекрасными).

Делает Regex.Replace() заменяющие нотации поддержки метода так, чтобы я мог все еще использовать единственный вызов? Что-то подобное как string.Format() метод делает, когда требуется отформатировать значения в формате строки (десятичные числа, даты и т.д....).

7
задан Robert Koritnik 5 May 2010 в 19:50
поделиться

2 ответа

Вы можете разделить $ {url} на две группы захвата - urlhead , с количеством символов, которое вы хотите отобразить, и urltail с остальными. Вот пример с 10 символами; это несколько упрощено, чтобы удалить условие, последний (? (? (external) (? = \)))) должен позаботиться об этом - он возвращает и захватывает последний ) при необходимости:

(?<outer>(?<=\())?
(?<scheme>http(?<secure>s)?://)?
(?<url>
    (?(scheme)
        (?:www\.)?
        |
        www\.
    )
    [a-z0-9]
    [-a-z0-9/+&@#/%?=~_()|!:,.;čšžćđ]{1,10}
)
(?<urltail>[-a-z0-9/+&@#/%?=~_()|!:,.;čšžćđ]+)
(?<ending>(?(outer)(?=\))))

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

<a href=\"http${secure}://${url}${urltail}\">http${secure}://${url}</a>
1
ответ дан 7 December 2019 в 18:41
поделиться

Вам нужно будет использовать перегрузку Regex.Replace, которая использует MatchEvaluator , делегат, который создает замещающий текст для вас.

См. Здесь: http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.matchevaluator.aspx

Технически это возможно только с помощью регулярных выражений, делая то, что Коби предлагает. Однако я не уверен, что хотел бы попросить кого-нибудь (включая себя через несколько месяцев) поддерживать это регулярное выражение.

1
ответ дан 7 December 2019 в 18:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: