» » Регулярные выражения для простых смертных

 

Регулярные выражения для простых смертных

Автор: admin от 16-05-2016, 17:35, посмотрело: 32

Здравствуйте, уважаемые дамы и господа.

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


Рано или поздно вам придется иметь дело с регулярными выражениями. Притом, какой у них сложный синтаксис, путаная документация и жесткая кривая обучения, большинство разработчиков удовлетворяются следующим: копипастят выражение со StackOverflow и надеются, что оно будет работать. Но что если бы в самом деле могли расшифровывать регулярные выражения и пользоваться ими на всю катушку? В этой статье я расскажу, почему следует еще раз присмотреться к регулярным выражениям, и как они могут пригодиться на практике.

Зачем нужны регулярные выражения?

Зачем вообще возиться с регулярными выражениями? Чем они могут помочь именно вам?


  • Сравнение с шаблоном: Регулярные выражения отлично помогают определять, соответствует ли строка тому или иному формату – например, телефонному номеру, адресу электронной почты или номеру кредитной карты.

  • Замена: При помощи регулярных выражений легко находить и заменять шаблоны в строке. Так, выражение text.replace(/s+/g, " ") заменяет все пробелы в text, например, " nt ", одним пробелом.

  • Извлечение: При помощи регулярных выражений легко извлекать из шаблона фрагменты информации. Например, name.matches(/^(Mr|Ms|Mrs|Dr).?s/i)[1] извлекает из строки обращение к человеку, например, "Mr" из "Mr. Schropp".

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

  • Код: Когда пишете код, можно пользоваться регулярными выражениями для поиска информации в файлах; так, в Atom для этого предусмотрен find and replace, а в командной строке — ack.

  • Четкость и лаконичность: Если вы с регулярными выражениями на «ты», то сможете выполнять весьма нетривиальные операции, написав минимальный объем кода.



Как писать регулярные выражения

Регулярные выражения проще всего изучить на примере. Допустим, вы пишете веб-страницу, на которой будет поле для ввода телефонного номера. Поскольку вы — ас веб-разработки, вам хочется дополнительно отображать на экране галочку, если телефонный номер валиден, и крестик X — если нет.

<input id="phone-number" type="text">
<label class="valid" for="phone-number">[img]http://habrahabr.ru/check.svg[/img]
<label class="invalid" for="phone-number">[img]http://habrahabr.ru/.svg[/img]
input:not([data-validation="valid"]) ~ label.valid,
input:not([data-validation="invalid"]) ~ label.invalid {
  display: none;
}
$("input").on("input blur", function(event) {
  if (isPhoneNumber($(this).val())) {
    $(this).attr({ "data-validation": "valid" });
    return;
  }

  if (event.type == "blur") {
    $(this).attr({ "data-validation": "invalid" });
  }
  else {
    $(this).removeAttr("data-validation");
  }
});


Теперь, если человек введет или вставит в поле валидный номер, то отобразится галочка. Если пользователь уберет курсор из поля ввода, а в поле при этом останется недопустимое значение, то отобразится крестик.
Поскольку вы знаете, что телефонные номера состоят из десяти цифр, первым делом проверяете, чтобы isPhoneNumber выглядел так:

function isPhoneNumber(string) {
  return /dddddddddd/.test(string);
}



В этой функции между символами / содержится регулярное выражение с десятью d', то есть, символами-цифрами. Метод test возвращает true, если регулярное выражение соответствует строке, в противном случае – false. Если выполнить isPhoneNumber("5558675309"), метод вернет true! Ура!

Однако, писать десять d – слегка муторная работа. К счастью, то же самое можно сделать и при помощи фигурных скобок.

function isPhoneNumber(string) {
  return /d{10}/.test(string);
}


Иногда, вводя телефонный номер, человек начинает с ведущей 1. Правда было бы неплохо, если бы ваше регулярное выражение обрабатывало и такие случаи? Это можно сделать при помощи символа?.

function isPhoneNumber(string) {
  return /1?d{10}/.test(string);
}


Символ ? означает «ноль или единица», поэтому теперь isPhoneNumber возвращает true как для «5558675309», так и для «15558675309»!

Пока isPhoneNumberвполне хороша, но мы упускаем одну ключевую деталь: регулярные выражения сплошь и рядом могут совпадать не со строкой, а с частью строки. Оказывается, isPhoneNumber("555555555555555555") возвращает true, поскольку в этой строке десять цифр. Проблему можно решить, воспользовавшись якорями ^ и $.

function isPhoneNumber(string) {
  return /^1?d{10}$/.test(string);
}


Грубо говоря, ^ соответствует началу строки, а $ — концу строки, поэтому теперь ваше регулярное выражение совпадет с целым телефонным номером.

Серьезный пример

Релиз страницы состоялся, она пользуется бешеным успехом, но есть существенная проблема. В США телефонный номер можно записать разными способами:


  • (234) 567-8901

  • 234-567-8901

  • 234.567.8901

  • 234/567-8901

  • 234 567 8901

  • +1 (234) 567-8901

  • 1-234-567-8901



Хотя пользователи и могут обойтись без пунктуации, им было бы гораздо проще вводить заранее отформатированный номер.

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

function isPhoneNumber(string) {
  return /^1?d{10}$/.test(string.replace(/D/g, ""));
}


Функция replace заменяет пустой строкой символ D, соответствующий любым символам кроме цифр. Глобальный флаг g приказывает функции заменить на регулярное выражение все совпадения, а не только первое.

Еще более серьезный пример

Ваша страница с телефонными номерами всем нравится, в офисе вы – король кулера. Однако, такие профессионалы как вы не останавливаются на достигнутом, поэтому вы хотите сделать страницу еще лучше.
North American Numbering Plan – это стандарт по составлению телефонных номеров, используемый в США, Канаде и еще 23 странах. В этой системе есть несколько простых правил:


  • Телефонный номер ((234) 567-8901) делится на три части: региональный код (234), код АТС (567) и номер абонента (8901).

  • В региональном коде и коде АТС первая цифра может быть любой от 2 до 9, а вторая и третья цифры – от 0 до 9.

  • В коде АТС 1 не может быть третьей цифрой, если вторая цифра – это 1.



  • Ваше регулярное выражение уже соответствует первому правилу, но нарушает второе и третье. Пока давайте разберемся со вторым. Новое регулярное выражение должно выглядеть примерно так:

    /^1?заморачиваться, то вам вряд ли понравится разбирать нерегулярные языки при помощи регулярных выражений.

    Не используйте их с очень сложными строками. Полное регулярное выражение для работы с электронной почтой состоит из 6 318 символов. Простое и приблизительное выглядит так: /^[^@]+@[^@]+.[^@.]+$/. Общее правило таково: если у вас получается регулярное выражение длиннее одной строки кода, то, возможно, стоит поискать другое решение.

    Источник: Хабрахабр

    Категория: Программирование

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

    Добавление комментария

    Имя:*
    E-Mail:
    Комментарий:
    Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
    Введите два слова, показанных на изображении: *