С терминал: Използване на регулярни изрази

Едно от нещата, които винаги съм обичал в терминала на 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/ Арх Linux: 11-03-2002 От Linux Рулес.

Това са трите реда, които съдържат думата "Linux", която, ако сме използвали цветовия трик, ще се появи подчертана. Имайте предвид, че той разпознава думата, която търсим, дори ако е част от по-дълга дума, както в "ArchLinux". Той обаче не откроява думата „linux“, която се появява в URL адреса „https://wiki.archlinux.org/“. Това е така, защото се появява там с малки букви "l" и ние го потърсихме с главни букви. Командата grep има опции за това, но няма да говоря за тях в статия, занимаваща се с регулярни изрази.

С този прост тест можем да направим първото заключение:

  • Нормален знак, поставен в регулярен израз, съвпада със себе си.

Което ще рече, че ако сложите буквата "а", тя ще търси буквата "а". Изглежда логично, нали? 🙂

Сега да предположим, че искаме да търсим думата "CentO", последвана от произволен знак, но само един знак. За това можем да използваме символа „.“, Който е заместващ знак, който съответства на всеки символ, но само на един:

grep 'CentO.' regex

И резултатът е:

CentOS: http://wiki.centos.org/
цента: 14-05-2004 03:32:38

Което означава, че включва „S“ в „CentOS“, въпреки че в един случай е с главни букви, а в друг с малки букви. Ако на това място се появи друг герой, той също ще го включи. Вече имаме второто правило:

  • Характерът "." съответства на всеки символ.

Вече не е толкова тривиално, колкото изглеждаше, но с това не можем да направим много. Да отидем малко по-нататък. Да предположим, че искаме да намерим редовете, в които се появяват 2002 и 2004 г. Те изглеждат като две търсения, но могат да бъдат направени наведнъж по следния начин:

grep '200[24]' regex

Което означава, че искаме да намерим числото 200, последвано от 2 или 4. И резултатът е следният:

ArchLinux: 11-03-2002
Gentoo: 31/03 /2002
CentOS: 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-03-2002 Gentoo: 31 CentOs: 14-05 2004 03:32:38 Debian: 16 г. Ubuntu: 20/10/2004

Сега ":" зад имената на дистрибуцията са маркирани, но не и тези в URL адресите, защото URL адресите имат "/" след тях.

  • Поставянето на символа "^" в началото на скоба съответства на всеки символ, с изключение на останалите символи в скобата.

Друго нещо, което можем да направим, е да посочим набор от знаци. Например, за да търсите произволно число, последвано от "-", ще изглежда така:

grep '[0-9]-' regex

С това определяме знак между 0 и 9 и след това знак минус. Нека видим резултата:

ArchLinux: 11-03-2002 CentOs: 14-05-2004 03: 32: 38

В скобите могат да бъдат посочени множество диапазони, за да се смесват дори диапазони с единични знаци.

  • Поставянето на два знака, разделени с "-" в скобите, съответства на всеки символ в диапазона.

Нека да видим сега дали можем да изберем първата част от URL адресите. Този, който казва „http“ или „https“. Те се различават само в крайните "s", така че нека го направим както следва:

grep -E 'https?' regex

Въпросният знак се използва, за да направи символа отляво по избор. Но сега добавихме опцията -E към командата. Това е така, защото разпитът е характеристика на разширените регулярни изрази. Досега използвахме основни регулярни изрази, така че не трябваше да влагаме нищо. Нека видим резултата:

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/

Така че вече имаме ново правило:

  • Символ, последван от "?" съответства на този знак или няма. Това важи само за разширени регулярни изрази.

Сега ще намерим две напълно различни думи. Нека да видим как да намерим редовете, които съдържат както думата "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

И резултатът и в двата случая ще бъде следният:

ArchLinux: 11-03-2002
Gentoo: 31/03 /2002
CentOS: 14-05-2004 03:32:38
Debian: 16/08/1993
Ubuntu: 20/10 /2004
  • Символите "{" и "}" с число между тях съвпадат с предишния знак, повторен посочения брой пъти.

Сега другият пример със скобите. Да предположим, че искаме да намерим думи, които имат между 3 и 6 малки букви. Можем да направим следното:

grep '[a-z]\{3,6\}' regex

И резултатът ще бъде следният:

- Л.иста de страницаs уики: ДА СЕrchLinux: HTTPS:/ /уики.archlinux.ORG/ Gтогава: HTTPS:/ /уики.gentoo.ORG/уики/MAin_Pвъзраст
CвхОПЕРАЦИОННА СИСТЕМА: HTTP:/ /уики.CentOS.ORG/ Дebian: HTTPS:/ /уики.Debian.ORG/ ИЛИзадънен край: HTTPS:/ /уики.Ubuntu.COM/ - Fти липсваш de Release: ДА СЕrch Linux: 11-03-2002 Gтогава: 31 г. C.вхOs: 14-05-2004 03:32:38
Debian: 16 Uзадънен край: 20 г. Dто е Linux Rулез.

Което, както виждате, не прилича много на това, което искахме. Това е така, защото регулярният израз намира буквите в други думи, които са по-дълги. Нека опитаме тази друга версия:

grep '\<[a-z]\{3,6\}\>' regex

Резултат:

- Списък на страниците уики: ArchLinux: HTTPS:/ /уики.archlinux.ORG/ Gentoo: HTTPS:/ /уики.gentoo.ORG/уики/ Main_Page CentOS: HTTP:/ /уики.CentOS.ORG/ Debian: HTTPS:/ /уики.Debian.ORG/ Ubuntu: HTTPS:/ /уики.Ubuntu.COM/

Това вече прилича повече на това, което искахме. Това, което направихме, е да изискваме думата да започва точно преди първата буква и да завършва точно след последната.

  • Символите "{" и "}" с две числа помежду си, разделени със запетая, съответстват на предишния знак, повтарящ се броя пъти, посочени от двете числа.

Нека сега разгледаме герой, който е първостепенно на „+“. Той е "*" и работата му е много подобна само, че съвпада с произволен брой символи, включително нула. Тоест, прави същото като „+“, но не изисква знакът отляво да се появява в текста. Например, нека опитаме да потърсим тези адреси, които започват в wiki и завършват в org:

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

Резултатът не е това, което търсим:

- Списък на wiki страниците:
ArchLinux: https://wiki.archlinux.org/
Gentoo: https://wiki.gentoo.org/wiki/Main_Page
CentOS: http://wiki.centos.org/
Дебиан: https://wiki.debian.org/
Ubuntu: https://wiki.ubuntu.com/
- Дати на издаване: Arch Linux: 11-03-2002
Gentoo: 312
CentOs: 14-05-2004 03:32:38
Debian: 163
Ubuntu: 204
Desde Linux Рулес.

Това е така, защото "." съвпада с каквото и да е, така че регулярният израз да съответства на последния знак от всеки ред, какъвто и да е той. Решението е следното:

grep '\.$' regex

Сега резултатът е това, което искаме:

Desde Linux Рулес.

Играта свърши

Въпреки че темата за регулярните изрази е толкова сложна, че бих дал за поредица статии, мисля, че вече ви причиних достатъчно болка. Ако сте успели да пристигнете, поздравления. И ако сте прочели всичко това на едно заседание, вземете аспирин или нещо подобно, защото не може да бъде добре.

Засега това е всичко. Ако тази статия ви харесва, може би можете да напишете друга. Междувременно ви препоръчвам да изпробвате всички регулярни изрази в терминала, за да видите ясно как работят. И не забравяйте: Само Чък Норис може да анализира HTML, използвайки регулярни изрази.


Оставете вашия коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *

*

*

  1. Отговорен за данните: Мигел Анхел Гатон
  2. Предназначение на данните: Контрол на СПАМ, управление на коментари.
  3. Легитимация: Вашето съгласие
  4. Съобщаване на данните: Данните няма да бъдат съобщени на трети страни, освен по законово задължение.
  5. Съхранение на данни: База данни, хоствана от Occentus Networks (ЕС)
  6. Права: По всяко време можете да ограничите, възстановите и изтриете информацията си.

  1.   Езекиел каза той

    Какъв би бил животът ни без регулярния израз?
    Статията е много полезна, но ще я прочета малко по малко. Благодаря много.

    1.    хексборг каза той

      Благодаря ви за коментар. Все още не вярвам, че статията ми е излязла. Излезе с известна грешка, но се надявам да е полезна. 🙂

  2.   Скалибур каза той

    Благодаря ти!

    Преди време трябваше да уча малко за регулярните изрази .. ..Благодаря ви за преподаването .. и ръководството стъпка по стъпка, за да науча всеки един от тях ..

    Много добре! .. .. Ще взема този аспирин .. ее

    1.    хексборг каза той

      Моля. Смелостта и че регулярните изрази не могат да бъдат с вас. 🙂

  3.   Танракс каза той

    Фантастична публикация! Добра работа. Чудя се колко часа ви отне 😀

    1.    хексборг каза той

      LOL !! Въпросът е: Колко часа щеше да ми отнеме, ако бях казал всичко, което възнамерявах да кажа? Безкраен !! 🙂

  4.   таммуз каза той

    едно нещо не знаех, добра статия!

    1.    хексборг каза той

      Благодаря ти. За мен е удоволствие да го споделя с вас.

  5.   helena_ryuu каза той

    чудесно обяснение. поздравления! наистина полезно!

    1.    хексборг каза той

      Радвам се, че го намерихте за полезен. Така че е удоволствие да пиша.

  6.   анти каза той

    Това трябва да отиде някъде специално. Харесайте Featured, но има много специфична полезност. Доста полезно, въпреки че бих искал да видя, че се прилага към Vim.

    1.    хексборг каза той

      Това е въпросът да си задам въпроса. Имам предвид още няколко статии за регулярни изрази. И бих могъл да говоря за vim в тях. Той има някои разлики от това, което обясних в тази статия. Въпросът е да продължите. 🙂

  7.   Fernando каза той

    Добре!

    Статията ви е много добра, любопитна е, наскоро (в момента) публикувах на моя уебсайт запис, който подготвях няколко дни, където събрах списък с метазнаци за регулярни изрази и някои примери. И беше честно да влезем DesdeLinux и вижте запис по същата тема!

    Ако е някаква утеха, моята е МНОГО ПОВЕЧЕ US

    Със сигурност регулярните изрази са едно от най-полезните неща, обикновено ги използвам, за да отрежа изхода на командите и да запазя частта, която ме интересува, и след това да взаимодействам с него в bash скрипт, например. Използвал съм ги много и в университета и те са от жизненоважно значение при изграждането на компилатори (при дефиницията на лексикографски и парсери). Накратко, цял свят.

    Поздрави и много много добра работа.

    1.    хексборг каза той

      Благодаря Ви много.

      Харесах и статията ви. По-кратък е от моя. Може да служи като бърза справка. Случайно е, че сме ги писали едновременно. Виждате, че хората се интересуват от темата. 🙂

  8.   Елъри каза той

    Регулярни изрази за манекени =), сега ми е по-ясно, между другото един от начините да има изход с цвят за grep е създаването на псевдоним в .bashrc псевдоним grep = 'grep –color = always', в случай че работи за някого .

    поздрави

    1.    хексборг каза той

      Вярно. Това е друг начин да го направите. Благодаря за приноса. 🙂

  9.   KZKG ^ Гаара каза той

    O_O ... принос !!! O_O ...
    Благодаря ви много за публикацията, чаках нещо такова известно време хахаха, вече го оставям отворено, за да го прочета спокойно у дома с нула караница, за да се концентрирам хахаха.

    Благодаря за статията, наистина го правя 😀

    1.    хексборг каза той

      Знаех, че ще ви хареса. LOL !! Истината е, че много неща липсват, но вече имам предвид втората част. 🙂

  10.   Елисер Татес каза той

    Страхотна статия, само да я бях прочел вчера, часът, който дадох днес, щеше да бъде още по-лесен за моите ученици!

    1.    хексборг каза той

      LOL !! Жалко, че закъснях, но се радвам, че е полезно. 🙂

  11.   ЛеоТоро каза той

    Накрая !!!, супер добър пост ... Най-накрая намерих нещо, което ясно обяснява регулярните изрази ...

    1.    хексборг каза той

      Има много информация там, но е по-трудно да се намери нещо, което е лесно за разбиране. Радвам се, че запълних тази празнина. 🙂

      Поздрави.

  12.   Шекспир Роудс каза той

    Ей, имам нужда от помощ, трябва да направя търсене в / var / logs с формат: yymmdd и дневниците идват като 130901.log -130901.log, трябва да търся всички, които са между 1 септември и 11 октомври Единственото нещо, което успях да направя, беше да премахна целия септември, но не знам как да направя цялата верига:

    пр .: 1309 [0-3] ми връща регистрационните файлове между 1 и 30 септември, но не знам как да попадна и в същата верига от 1 до 11 октомври.

    1.    хексборг каза той

      Да го направите с помощта на регулярни изрази е малко сложно. Хрумна ми, че нещо подобно може да работи:

      13(09[0-3]|10(0|1[01]))

      Това е разширен регулярен израз. Не казвате кой инструмент използвате, така че не мога да ви дам повече подробности.

      Както и да е, мисля, че това е така, вместо да използваме регулярни изрази, по-добре е да го направим с find. Можете да опитате нещо подобно:

      намирам. -newermt '01 сеп '-a! -newermt '11 oct '-печат

      Късмет. Надявам се, че това може да ви помогне.

  13.   чипо каза той

    Здравейте! На първо място, исках да ви благодаря за вашата работа, тъй като тази страница е в моя "топ 3" на най-добрите Linux сайтове.
    Практикувах и не знаех защо RegExp на телефонен номер не работи и беше, че ми липсваше „-E“ (което разбрах благодарение на тази публикация).
    Исках да ви попитам дали не знаете добър pdf или сайт, където има упражнения на RegExp, въпреки че с малко въображение можете да се упражнявате да ги измисляте сами.

    Поздрави, Пабло.

  14.   Кали каза той

    Много добре, току-що прочетох всичко и да сега имам нужда от аспирин 🙂

  15.   Оскар каза той

    Най-доброто обяснение, което съм виждал за регулярните изрази. Благодаря на автора, че сподели тази работа.

    За поздрав.

  16.   Алексадер каза той

    Много ми хареса едно много добро обяснение