Одна из вещей, которые мне всегда нравились в терминале Linux, - это то, что можно достичь с помощью регулярных выражений. Если нам нужно найти сложный текст или заменить его чем-то другим, использование регулярных выражений может значительно упростить работу. Начнем с начала:
Что такое регулярное выражение?
Регулярное выражение - это серия специальных символов, которые позволяют нам описать текст, который мы хотим найти. Например, если бы мы хотели найти слово «linux», было бы достаточно ввести это слово в используемую нами программу. Само слово является регулярным выражением. Пока это кажется очень простым, но что, если мы хотим найти все числа в определенном файле? Или все строки, начинающиеся с заглавной буквы? В таких случаях вы больше не можете использовать простое слово. Решение - использовать регулярное выражение.
Регулярные выражения и шаблоны файлов.
Прежде чем я перейду к регулярным выражениям, я хочу прояснить распространенное заблуждение о регулярных выражениях. Регулярное выражение - это не то, что мы указываем в качестве параметра в таких командах, как rm, cp и т. Д. Для обозначения различных файлов на жестком диске. Это будет шаблон файла. Регулярные выражения, хотя и похожи в том, что они используют некоторые общие символы, различны. Шаблон файла запускается для файлов на жестком диске и возвращает те, которые полностью соответствуют шаблону, в то время как регулярное выражение запускается для текста и возвращает строки, содержащие искомый текст. Например, регулярное выражение, соответствующее шаблону *.*
это было бы что-то вроде ^.*\..*$
Типы регулярных выражений.
Не все программы используют одни и те же регулярные выражения. Не намного меньше. Существует несколько типов более или менее стандартных регулярных выражений, но есть программы, которые немного изменяют синтаксис, включают собственные расширения или даже используют совершенно другие символы. Поэтому, если вы хотите использовать регулярные выражения в программе, которую вы плохо знаете, первое, что нужно сделать, - это посмотреть руководство или документацию программы, чтобы увидеть, на что похожи регулярные выражения, которые она распознает.
Прежде всего, существует два основных типа регулярных выражений, которые содержатся в стандарте POSIX, который используется инструментами Linux. Это базовые и расширенные регулярные выражения. Многие команды, работающие с регулярными выражениями, такие как grep или sed, позволяют использовать эти два типа. О них я расскажу ниже. Существуют также регулярные выражения в стиле PERL, а есть такие программы, как vim или emacs, которые используют их варианты. В зависимости от того, что мы хотим сделать, может быть более подходящим использовать одно или другое.
Тестирование регулярных выражений.
Синтаксис регулярных выражений совсем нетривиален. Когда нам нужно написать сложное регулярное выражение, мы окажемся перед строкой специальных символов, которые невозможно понять с первого взгляда, поэтому для того, чтобы научиться их использовать, важно иметь способ выполнять все необходимые нам тесты и видеть результаты легко. Вот почему я сейчас собираюсь поместить несколько команд, с помощью которых мы сможем проводить тесты и экспериментировать со всем, что нам нужно, пока у нас не будут преобладать регулярные выражения.
Первая - это команда grep. Это команда, которую мы будем использовать чаще всего для поиска. Синтаксис следующий:
grep [-E] 'REGEX' FICHERO
COMANDO | grep [-E] 'REGEX'
Я рекомендую всегда заключать регулярные выражения в одинарные кавычки, чтобы оболочка не справлялась с этим. Первый способ - найти в файле регулярное выражение. Второй позволяет фильтровать вывод команды с помощью регулярного выражения. По умолчанию grep использует базовые регулярные выражения. Параметр -E предназначен для использования расширенных регулярных выражений.
Уловка, которая может помочь нам увидеть, как работают регулярные выражения, - это включить использование цвета в команде grep. Таким образом, будет выделена часть текста, соответствующая используемому нами регулярному выражению. Чтобы активировать цвет в команде grep, просто убедитесь, что переменная среды GREP_OPTIONS
содержать в ценности --color
, что можно сделать с помощью этой команды:
GREP_OPTIONS=--color
Мы можем поместить его в .bashrc, чтобы он всегда был активен.
Другой способ использовать регулярные выражения - использовать команду sed. Это больше подходит для замены текста, но также может использоваться для поиска. Синтаксис для него будет таким:
sed -n[r] '/REGEX/p' FICHERO
COMANDO | sed -n[r] '/REGEX/p'
Команда sed также по умолчанию использует базовые регулярные выражения, вы можете использовать расширенные регулярные выражения с параметром -r.
Еще одна команда, которую я также хочу назвать, - это awk. Эта команда может использоваться для многих вещей, поскольку позволяет писать сценарии на вашем собственном языке программирования. Если мы хотим найти регулярное выражение в файле или в выводе команды, способ его использования будет следующим:
awk '/REGEX/' FICHERO
COMANDO | awk '/REGEX/'
Эта команда всегда использует расширенные регулярные выражения.
Для проведения наших тестов нам также понадобится текст, который служит примером для поиска по нему. Мы можем использовать следующий текст:
- Lista de páginas wiki: ArchLinux: https://wiki.archlinux.org/ Gentoo: https://wiki.gentoo.org/wiki/Main_Page CentOS: http://wiki.centos.org/ Debian: https://wiki.debian.org/ Ubuntu: https://wiki.ubuntu.com/ - Fechas de lanzamiento: Arch Linux: 11-03-2002 Gentoo: 31/03/2002 CentOs: 14-05-2004 03:32:38 Debian: 16/08/1993 Ubuntu: 20/10/2004 Desde Linux Rulez.
Это текст, который я буду использовать для примеров остальной части сообщения, поэтому я рекомендую вам скопировать его в файл, чтобы он был под рукой из терминала. Вы можете указать желаемое имя. Я назвал это регулярным выражением.
Начало урока.
Теперь у нас есть все необходимое для тестирования регулярных выражений. Пойдем мало-помалу. Я собираюсь привести несколько примеров поиска с регулярными выражениями, в которых я объясню, для чего нужен каждый символ. Это не очень хорошие примеры, но поскольку у меня будет очень длинный пост, я не хочу больше его усложнять. И я просто коснусь того, что можно сделать с помощью регулярных выражений.
Самый простой из всех - найти определенное слово, например, предположим, что мы хотим найти все строки, содержащие слово «Linux». Это самый простой способ, так как нам нужно только написать:
grep 'Linux' regex
И мы видим результат:
АркаLinux: https://wiki.archlinux.org/ Arch Linux: 11-03-2002 С Linux Рулез.
Это три строки, которые содержат слово «Linux», которое, если мы воспользуемся цветовым трюком, будет выделено. Обратите внимание, что он распознает слово, которое мы ищем, даже если оно является частью более длинного слова, как в «ArchLinux». Однако он не выделяет слово «linux», которое появляется в URL-адресе «https://wiki.archlinux.org/». Это потому, что он появляется там со строчной буквой «l», а мы искали его в верхнем регистре. У команды grep есть параметры для этого, но я не буду говорить о них в статье, посвященной регулярным выражениям.
С помощью этого простого теста мы можем сделать первый вывод:
- Обычный символ, помещенный в регулярное выражение, соответствует самому себе.
Lo que viene a decir que si pones la letra «a» buscará la letra «a». Parece lógico, ¿verdad?
Теперь предположим, что мы хотим найти слово «CentO», за которым следует любой символ, но только один символ. Для этого мы можем использовать символ «.», Который является подстановочным знаком, который соответствует любому символу, но только одному:
grep 'CentO.' regex
И вот результат:
CentOS: http://wiki.centos.org/ CentOS: 14-05-2004 03:32:38
Это означает, что он включает букву «S» в «CentOS», хотя в одном случае это заглавная буква, а в другом - строчная. Если в этом месте появится какой-либо другой персонаж, он также будет включен. У нас уже есть второе правило:
- Персонаж "." соответствует любому символу.
Это уже не так тривиально, как казалось, но с этим мы мало что можем сделать. Пойдем немного дальше. Предположим, мы хотим найти строки, в которых фигурируют 2002 и 2004. Это похоже на два поиска, но их можно выполнить сразу следующим образом:
grep '200[24]' regex
Это означает, что мы хотим найти число 200, за которым следует 2 или 4. И результат следующий:
АрхЛинукс: 11-03-2002 Gentoo: 31 /2002 Центров: 14-05-2004 03:32:38 Ubuntu: 20/10/2004
Это подводит нас к третьему правилу:
- Несколько символов, заключенных в скобки, соответствуют любому из символов в скобках.
Скобки дают больше люфта. их также можно использовать для исключения символов. Например, предположим, что мы хотим найти сайты, на которых появляется символ ":", но не следует "/". Команда будет такой:
grep ':[^/]' regex
Просто поставьте «^» в качестве первого символа в скобках. Вы можете поместить всех желаемых персонажей ниже. Результат этой последней команды следующий:
ArchLinux: https://wiki.archlinux.org/ Gentoo: https://wiki.gentoo.org/wiki/Main_Page CentOS: http://wiki.centos.org/ Debian: https://wiki.debian.org/ Ubuntu: https://wiki.ubuntu.com/ Arch Linux: 11 Gentoo: 31 CentOs: 14-05-2004 03:32:38 Debian: 16 Ubuntu: 20/10/2004
Теперь ":" за именами дистрибутивов выделяются, но не в URL-адресах, потому что URL-адреса имеют "/" после них.
- Помещение символа «^» в начало скобки соответствует любому символу, кроме других символов в скобках.
Еще мы можем указать диапазон символов. Например, для поиска любого числа, за которым следует знак «-», это будет выглядеть так:
grep '[0-9]-' regex
При этом мы указываем символ от 0 до 9, а затем знак минус. Посмотрим на результат:
Арх Линукс: 11-03-Центров 2002 года: 14-05-2004 03:32:38
Вы можете указать несколько диапазонов в скобках, чтобы даже смешивать диапазоны с отдельными символами.
- Размещение двух символов, разделенных знаком «-» в скобках, соответствует любому символу в пределах диапазона.
Теперь посмотрим, сможем ли мы выбрать первую часть URL-адресов. Тот, который говорит "http" или "https". Они различаются только конечными буквами "s", поэтому сделаем это следующим образом:
grep -E 'https?' regex
Знак вопроса используется для обозначения символа слева от него необязательным. Но теперь мы добавили в команду параметр -E. Это потому, что опрос - это функция расширенных регулярных выражений. До сих пор мы использовали базовые регулярные выражения, поэтому не нужно было ничего добавлять. Посмотрим на результат:
АрхЛинукс: протокол HTTPS: //wiki.archlinux.org/ Gentoo: протокол HTTPS: //wiki.gentoo.org/wiki/Main_Page CentOS: HTTP: //wiki.centos.org/ Debian: протокол HTTPS: //wiki.debian.org/ Ubuntu: протокол HTTPS: //wiki.ubuntu.com/
Итак, у нас уже есть новое правило:
- Символ, за которым следует "?" соответствует этому символу или нет. Это действительно только для расширенных регулярных выражений.
Теперь мы найдем два совершенно разных слова. Давайте посмотрим, как найти строки, содержащие слово «Debian» и «Ubuntu».
grep -E 'Debian|Ubuntu' regex
С помощью вертикальной черты мы можем разделить два или более разных регулярных выражения и найти строки, соответствующие любому из них:
Debian: https://wiki.debian.org/ Ubuntu: https://wiki.ubuntu.com/ Debian: 16 / 08 / 1993 Ubuntu: 20 / 10 / 2004
- Символ "|" служит для разделения нескольких регулярных выражений и соответствует любому из них. Это также характерно для расширенных регулярных выражений.
Давай продолжим. Теперь мы будем искать слово «Linux», но только там, где оно не прикреплено к другому слову слева. Сделать это можно так:
grep '\
Здесь важным символом является «<», но его нужно экранировать, поставив перед ним «\», чтобы grep интерпретировал его как специальный символ. Результат такой:
Арка Linux: 11-03-2002 С Linux Рулез.
Вы также можете использовать "\>" для поиска слов, которые не расположены рядом друг с другом. Приведем пример. Попробуем эту команду:
grep 'http\>' regex
Результат такой:
CentOS: HTTP: //wiki.centos.org/
Вышел «Http», но не «https», потому что в «https» все еще есть символ справа от «p», который может быть частью слова.
- Символы «<» и «>» соответствуют началу и концу слова соответственно. Эти символы должны быть экранированы, чтобы они не интерпретировались как буквальные символы.
Мы идем с вещами немного сложнее. Символ «+» соответствует символу слева от него, повторяется хотя бы один раз. Этот символ доступен только в расширенных регулярных выражениях. С его помощью мы можем искать, например, последовательности нескольких последовательных чисел, начинающихся с ":".
grep -E ':[0-9]+' regex
Результат:
CentOs: 14-05-2004 03: 32: 38
Число 38 также выделено, потому что оно также начинается с «:».
- Символ «+» соответствует символу слева от него, повторяется хотя бы один раз.
Вы также можете контролировать количество повторений с помощью "{" и "}". Идея состоит в том, чтобы заключить в фигурные скобки число, которое указывает точное количество повторений, которое мы хотим. Также можно поставить диапазон. Давайте посмотрим на примеры двух случаев.
Сначала мы собираемся найти все имеющиеся четырехзначные последовательности:
grep '[0-9]\{4\}' regex
Обратите внимание, что фигурные скобки должны быть экранированы, если мы используем базовые регулярные выражения, но не если мы используем расширенные. С расширенным это будет так:
grep -E '[0-9]{4}' regex
И результат в обоих случаях будет таким:
АрхЛинукс: 11-03-2002 Gentoo: 31 /2002 Центров: 14-05-2004 03:32:38 Debian: 16/08/1993 Ubuntu: 20/10 /2004
- Символы "{" и "}" с числом между ними соответствуют предыдущему символу, повторяемому указанное количество раз.
Теперь другой пример с фигурными скобками. Предположим, мы хотим найти слова, содержащие от 3 до 6 строчных букв. Мы могли сделать следующее:
grep '[a-z]\{3,6\}' regex
И результат будет такой:
- Lишта de páginas Вики: TORCHLприток: протокол HTTPS:/ /Вики.Archlinux.org/ ГEntoo: протокол HTTPS:/ /Вики.папуасских.org/Вики/Mайн_Pвозраст CЛОРОС: HTTP:/ /Вики.CentOS.org/ Dэбианский: протокол HTTPS:/ /Вики.Debian.org/ ИЛИ ЖЕбунт: протокол HTTPS:/ /Вики.Ubuntu.com/ - Fты скучаешь de запуск: TORCH Lприток: 11-03-2002 GEntoo: 31 CЛОРOs: 14-05-2004 03:32:38 Dэбианский: 16 Uбунт: 20 Dэто Lприток Rулез.
Что, как видите, не очень похоже на то, что мы хотели. Это потому, что регулярное выражение находит буквы в других словах, которые длиннее. Попробуем другую версию:
grep '\<[a-z]\{3,6\}\>' regex
Результат:
- Список страниц Вики: ArchLinux: протокол HTTPS:/ /Вики.архлинукс.org/ Gentoo: протокол HTTPS:/ /Вики.папуасских.org/Вики/ Main_Page CentOS: HTTP:/ /Вики.CentOS.org/ Debian: протокол HTTPS:/ /Вики.Debian.org/ Ubuntu: протокол HTTPS:/ /Вики.Ubuntu.com/
Это уже больше похоже на то, что мы хотели. Мы потребовали, чтобы слово начиналось непосредственно перед первой буквой и заканчивалось сразу после последней.
- Символы "{" и "}" с двумя числами между ними, разделенными запятой, соответствуют предыдущему символу, повторяющемуся количество раз, указанное двумя числами.
Давайте теперь посмотрим на символ, который стоит перед знаком «+». Это «*», и его действие очень похоже, только оно соответствует любому количеству символов, включая ноль. То есть он делает то же самое, что и «+», но не требует, чтобы символ слева от него появлялся в тексте. Например, давайте попробуем найти те адреса, которые начинаются в вики и заканчиваются в организации:
grep 'wiki.*org' regex
Посмотрим на результат:
ArchLinux: https: //wiki.archlinux.org/ Gentoo: https: //wiki.gentoo.org/ wiki / Main_Page CentOS: http: //wiki.centos.org/ Debian: https: //wiki.debian.org/
Идеальный.
Теперь последний персонаж, которого мы увидим. Символ «\» используется для экранирования символа справа, так что он теряет свое особое значение. Например: предположим, мы хотим найти линии, заканчивающиеся точкой. Первое, что может прийти в голову, может быть следующее:
grep '.$' regex
Результат - не то, что мы ищем:
- Список вики-страниц: АрхЛинукс: https://wiki.archlinux.org/ Gentoo: https://wiki.gentoo.org/wiki/Main_Pag.e CentOS: http://wiki.centos.org./ Дебиан: https://wiki.debian.org/ Убунту: https://wiki.ubuntu.com/ - Даты выпуска: Arch Linux: 112 Gentoo: 312 CentOs: 14-05-2004 03:32:38 Debian: 163 Ubuntu: 204 Из Linux Rulez.
Это потому, что "." он соответствует чему угодно, поэтому регулярное выражение соответствует последнему символу каждой строки, какой бы она ни была. Решение такое:
grep '\.$' regex
Результат - то, что мы хотим:
Из Linux Rulez.
Game Over
Хотя тема регулярных выражений настолько сложна, что я бы посвятил ей серию статей, я думаю, что уже причинил вам достаточно боли. Если вам удалось приехать, поздравляю. И если вы прочитали все это сразу, примите аспирин или что-то в этом роде, потому что это не может быть хорошо.
А пока это все. Если вам понравилась эта статья, может, я напишу другую. А пока я рекомендую вам попробовать все регулярные выражения в терминале, чтобы понять, как они работают. И помните: только Чак Норрис может анализировать HTML с помощью регулярных выражений.
Какой была бы наша жизнь без регулярного выражения?
Статья очень полезная, но я буду читать ее понемногу. Большое спасибо.
Спасибо за комментарий. Я до сих пор не верю, что моя статья вышла. 🙂 Вышло с ошибкой, но я надеюсь, что это полезно. 🙂
Спасибо, ссссссс! ..
Давным-давно мне пришлось немного изучить регулярные выражения .. Я благодарю вас за обучение .. и пошаговое руководство по изучению каждого из них ..
Очень хорошо! .. Я собираюсь получить аспирин .. э-э
Пожалуйста. Мужество и то, что регулярные выражения не могут с тобой. 🙂
Фантастический пост! Прекрасная работа. Интересно, сколько часов у тебя ушло 😀
СМЕШНО!! Возникает вопрос: сколько часов мне понадобилось бы, если бы я сказал все, что собирался сказать? Бесконечный !! 🙂
одно я не знал, хорошая статья!
Спасибо. Приятно поделиться с вами.
отличное объяснение. поздравляю! действительно полезно!
Я рад, что ты нашел это полезным. Так что писать одно удовольствие.
Это должно быть что-то особенное. Подобно избранному, но у него есть очень специфическая полезность. Довольно полезно, хотя я бы хотел, чтобы это применимо к Vim.
Это вопрос, который задаю себе. У меня есть еще несколько статей о регулярных выражениях. И я мог бы говорить о vim в них. Он имеет некоторые отличия от того, что я объяснил в этой статье. Вопрос в том, как с этим справиться. 🙂
Хорошо!
Ваша статья очень хорошая, любопытная, недавно (прямо сейчас) я опубликовал на своем сайте запись, которую я готовил несколько дней, где я собрал список метасимволов для регулярных выражений и несколько примеров. И было справедливо войти в DesdeLinux и увидеть запись на ту же тему!
Если это утешает, то у меня НАМНОГО БОЛЬШЕ КИСКИ 😀
Конечно, регулярные выражения - одна из самых полезных вещей, я обычно использую их для обрезки вывода команд и сохранения той части, которая меня интересует, а затем, например, взаимодействую с ней в сценарии bash. Я также много использовал их в университете, и они имеют жизненно важное значение при создании компиляторов (в определении лексикографических и синтаксических анализаторов). Короче, целый мир.
Привет и очень хорошая работа.
Большое спасибо.
Мне тоже понравилась твоя статья. Он более лаконичен, чем мой. Он может служить кратким справочником. Это совпадение, что мы написали их одновременно. Вы можете видеть, что людям интересна тема. 🙂
Регулярные выражения для чайников =), теперь мне стало понятнее, кстати, один из способов получить вывод с цветом для grep - это создать псевдоним в .bashrc alias grep = 'grep –color = always', если он у кого-то работает.
привет
Правда. Это еще один способ сделать это. Спасибо за вклад. 🙂
О_О… кусок вклада !!! О_О ...
Большое спасибо за пост, я ждал чего-то вроде этого какое-то время, лол, я оставляю его открытым, чтобы спокойно прочитать его дома без каких-либо проблем, чтобы сосредоточиться, лол
Спасибо за статью, правда
Я знал, что тебе это понравится. СМЕШНО!! Правда в том, что многого не хватает, но у меня уже есть вторая часть. 🙂
Отличная статья, если бы я прочитал ее вчера, урок, который я читал сегодня, был бы еще проще для моих учеников!
СМЕШНО!! Жаль, что я опоздал, но рад, что это помогло. 🙂
Наконец !!!, супер хороший пост .... Наконец-то я нашел кое-что, что четко объясняет регулярные выражения ...
Информации много, но труднее найти что-то, что легко понять. Я рад, что заполнил этот пробел. 🙂
Привет.
Привет, мне нужна помощь, мне нужно выполнить поиск в / var / logs в формате: yymmdd, а журналы выглядят так: 130901.log -130901.log, я должен искать все те, которые находятся в период с 1 сентября по 11 октября , Единственное, что мне удалось сделать, это удалить весь сентябрь, но я не знаю, как сделать всю цепочку:
Пример: 1309 [0-3] возвращает мне журналы с 1 по 30 сентября, но я не знаю, как попасть в ту же цепочку с 1 по 11 октября.
Сделать это с помощью регулярных выражений немного сложно. Мне приходит в голову, что что-то вроде этого может сработать:
13(09[0-3]|10(0|1[01]))
Это расширенное регулярное выражение. Вы не говорите, какой инструмент вы используете, поэтому я не могу дать вам более подробную информацию.
Во всяком случае, я думаю, что это так, вместо использования регулярных выражений лучше использовать find. Вы можете попробовать что-то вроде этого:
находить. -newermt '01 sep '-a! -newermt '11 oct '-print
Удачи. Надеюсь, это поможет тебе.
Здравствуйте! Прежде всего, я хотел бы поблагодарить вас за вашу работу, так как эта страница входит в мою «тройку» лучших сайтов Linux.
Я тренировался и не знал, почему у меня не работает регулярное выражение для телефонного номера, и мне не хватало «-E» (что я понял благодаря этой публикации).
Я хотел спросить вас, если вы не знаете хорошего pdf-файла или сайта, где есть упражнения по RegExp, хотя, проявив немного воображения, вы можете попрактиковаться в их изобретении.
Привет, Пабло.
Очень хорошо, я только что все это прочитала, и да, теперь мне нужен аспирин 🙂
Лучшее объяснение регулярных выражений, которое я видел. Моя благодарность автору за то, что поделился этой работой.
Приветствие.
Мне очень понравилось очень хорошее объяснение