Журнал LinuxFormat - перейти на главную

LXF133:Grep

Материал из Linuxformat
Перейти к: навигация, поиск

Содержание

grep Супер-поиск по ко­ман­де

Лю­би­те ко­манд­ную стро­ку и хо­ти­те дос­тичь боль­ше­го? Ис­сле­дуй­те grep с Фэй ‘Шер­лок’ Уиль­ямс – и отныне ни­че­го уже не по­те­ряе­те.

Коман­да grep – мощней­шее сред­ство по­иска в фай­лах. Как и со мно­ги­ми ути­ли­та­ми команд­ной стро­ки, осво­ившись в ней, вы об­на­ру­жи­те, что она уди­ви­тель­но бы­ст­ра и точ­на. Од­на­ко мно­гие поль­зо­ва­те­ли Linux снис­хо­дят до изучения не бо­лее од­ной-двух оп­ций grep, по­сле че­го при­ме­ня­ют их как спо­соб по­иска «за все». А ведь чу­ток вре­мени, по­тра­ченно­го на изу­чение воз­мож­но­стей grep, оку­пит­ся сто­ри­цей – и нет ниче­го при­ятнее, чем точ­ное знание, как по коман­де мгно­венно по­лу­чить нуж­ный ре­зуль­тат. Мы начнем с основ и на­ра­бо­та­ем ба­гаж ва­ри­ан­тов ис­поль­зо­вания grep, а за­вер­шим все кое-ка­ки­ми улов­ка­ми – что­бы про­ве­рить, ал­че­те ли вы еще.


На рисунке при­ве­ден при­мер поиска в фай­ле ка­лен­да­ря OpenBSD. Такие уста­нов­ле­ны по умол­чанию в Ubuntu, Mint и мно­гих дру­гих ди­ст­ри­бу­ти­вах, и да­же на Mac. А ес­ли у вас (как и у меня) Fedora, и вы не же­лае­те оста­вать­ся в сто­роне, до­ба­вьте их вруч­ную, выбрав в сво­ем ра­бо­чем сто­ле оп­цию Систе­ма > Ад­минист­ри­рование > До­ба­вить/Уда­лить при­ло­жение. Най­ди­те calendar, устано­ви­те фла­жок ря­дом с Ути­ли­той на­по­ми­нания и на­жми­те При­менить. Или про­сто вы­полните yum install calendar в командной стро­ке. А те­перь о глав­ном.

Про­стой по­иск

Коман­да grep рас­по­зна­ет сле­дую­щее:

  1. Лю­бые оп­ции фильт­ра­ции ре­зуль­та­тов поиска.
  2. Стро­ку (или шаб­лон) иско­мо­го.
  3. Ме­сто осу­ще­ств­ления по­иска – файл или ка­та­лог.

Для при­ме­ра тут же оп­ро­буй­те:

grep first /usr/share/calendar/calendar.history

Об­су­дим по­лу­чен­ное. Мы по­про­си­ли grep най­ти все вхо­жде­ния стро­ки ‘first’ в фай­ле calendar.history. Пом­ни­те, что grep чув­ст­ви­тель­на к ре­ги­ст­ру – попробуйте выполнить grep First /usr/share/calendar/calendar.history и срав­ни­те то, что по­лу­чит­ся в ре­зуль­та­те.


Ес­ли вы хо­ти­те осу­ще­ст­вить по­иск без уче­та за­глав­ных и строчных букв, до­бавь­те оп­цию -i для иг­но­ри­ро­ва­ния ре­ги­ст­ра.

grep -i first /usr/share/calendar/calendar.history

По­ка все хо­ро­шо. А вдруг не­об­хо­ди­мо вы­пол­нить по­иск в несколь­ких фай­лах? Ка­лен­да­рей, ко­то­рые вы за­хо­ти­те про­смотреть, не­ма­ло, так что сме­ни­те путь к фай­лу на ка­та­лог и до­бавьте оп­цию -r, что­бы по­иск grep осу­ще­ст­в­лял­ся ре­кур­сив­но по всем фай­лам и под­ка­та­ло­гам, на­хо­дя­щим­ся в ука­зан­ном ка­та­ло­ге:

grep -ir first /usr/share/calendar

Ка­ж­дая стро­ка вы­во­да те­перь пред­ва­ря­ет­ся име­нем фай­ла. Заме­тим, что по­ря­док до­бав­ле­ния оп­ций по­сле сим­во­ла ‘-’ ро­ли не иг­ра­ет.

Ино­гда при­ме­ры, при­ве­ден­ные вы­ше, вас спа­са­ют; ес­ли вы ище­те пись­мо, ко­то­рое на­пи­са­ли не­ко­му До­ну Джен­кин­су, и знаете, что оно где-то в до­маш­нем ка­та­ло­ге, вы, ве­ро­ят­но, най­де­те файл при по­мо­щи:

grep -r Jenkins /home/faye

Но что ес­ли вы за­пус­ти­ли ко­ман­ду grep и не по­лу­чи­ли ожи­даемо­го ре­зуль­та­та, или по­лу­чи­ли столь­ко сов­па­де­ний, что не мо­жете от­ли­чить од­ну стро­ку от дру­гой?

На­страи­ва­ем вы­вод

Да­вай­те уп­ро­стим вос­при­ятие то­го, что мы де­ла­ем, вклю­чив опцию под­свет­ки в grep. На сей раз по­ищем ‘war’.

grep -ri --color=auto war /usr/share/calendar/


Уже луч­ше! И те­перь мож­но уви­деть ис­ко­мую стро­ку (ес­ли у вас Linux Mint, под­цвет­ка вклю­че­на по умол­ча­нию). Да­лее, из­ба­вим­ся от всех под­строк, по­сколь­ку grep вы­во­дит все сов­па­де­ния, да­же ес­ли они яв­ля­ют­ся ча­стью дру­гих слов. На­при­мер, наш по­иск war так­же при­хва­тит стро­ку с "Rod Stewart". Это­го мож­но из­бе­жать, запро­сив по­иск толь­ко пол­ных слов при по­мо­щи оп­ции -w – ко­ли­чест­во сов­па­де­ний умень­шит­ся на две тре­ти. Об этом мы уз­на­ли, заста­вив grep под­счи­тать ко­ли­че­ст­во вхо­ж­де­ний, вме­сто их пря­мо­го вы­во­да, по оп­ции -c:

grep -riwc war /usr/share/calendar

Вид­но, что grep вы­во­дит ко­ли­че­ст­во сов­па­де­ний для всех фай­лов, в ко­то­рых осу­ще­ст­в­лял­ся по­иск. Ес­ли вы ис­ка­ли в един­ст­вен­ном фай­ле, вер­нет­ся од­но чис­ло.

Пре­ж­де чем дви­нуть­ся даль­ше, еще кое-что. Оты­ски­вая бо­лее од­но­го сло­ва, сле­ду­ет поль­зо­вать­ся оди­ноч­ны­ми ка­выч­ка­ми для уче­та про­бе­лов:

grep -ri ‘civil war’ /usr/share/calendar

Все это хо­ро­шо, но вот по­иск че­го-то вро­де “$20” да­ет не­что ужас­но не­вер­ное. Что слу­чи­лось?


ОК, вам сле­ду­ет знать о grep еще кое-что, и это тот факт, что он раз­ра­ба­ты­вал­ся для ра­бо­ты с шаб­ло­на­ми или ре­гу­ляр­ны­ми вы­ра­же­ния­ми. Это об­шир­ная те­ма, но вот вам ее верш­ки (см. приме­ры вни­зу или же загляните в LXF80, ес­ли хо­ти­те узнать боль­ше). Сим­во­лы вро­де $*.?+ име­ют свои осо­бые зна­че­ния и по­зво­ля­ют ис­кать в фай­лах слож­ные и точ­ные шаб­ло­ны. Ес­ли вы ище­те стро­ку, со­дер­жа­щую эти спец­сим­во­лы, пред­ва­ри­те их об­рат­ным слэ­шем:

grep -ri ‘\$20’ /home/faye/statement.txt

Ина­че grep ин­тер­пре­ти­ру­ет сим­вол не про­сто как ли­те­рал, и ре­зуль­тат мо­жет со­дер­жать то, что вы хо­те­ли по­лу­чить, а может, и нет.

На­ко­нец, при же­ла­нии со­хра­нить ре­зуль­та­ты по­ис­ка мож­но пе­ре­на­пра­вить вы­вод grep в файл, сле­дую­щим об­ра­зом:

grep -riw first /usr/share/calendar > /home/faye/search.txt

Будь­те ос­то­рож­ны, по­сколь­ку, со­хра­нив файл в том же ка­тало­ге (или под­ка­та­ло­ге), где осу­ще­ст­в­лял­ся ре­кур­сив­ный по­иск, вы мо­же­те уго­дить в бес­ко­неч­ный цикл: grep при­мет­ся вы­да­вать вы­вод о соз­да­вае­мых са­мим же фай­лах. Ес­ли вы слу­чай­но это сде­ла­ли, про­сто на­жми­те Ctrl+C для вы­хо­да из цик­ла и уда­ли­те файл ре­зуль­та­та, по­сколь­ку он яв­но бу­дет мас­сив­ным.

Став зав­зя­тым ли­нук­сои­дом, вы об­на­ру­жи­те, что grep не­заме­ним, но ес­ли вы дей­ст­ви­тель­но же­лае­те ос­во­ить эту ко­ман­ду, сле­ду­ет пред­при­нять не­сколь­ко до­пол­ни­тель­ных ша­гов. Во-первых, по­поль­зуй­тесь man-стра­ни­цей (по за­вер­ше­нии чте­ния нажми­те Q):

man grep

Так вы по­лу­чи­те де­таль­ное опи­са­ние оп­ций grep. Сто­ит так­же попро­бо­вать ко­ман­ду help:

grep --help

Она пре­вос­ход­на для бы­ст­ро­го на­по­ми­на­ния. Она со­об­щит, как вста­вить в вы­вод но­ме­ра строк (ве­ли­ко­леп­но для фай­лов с исход­ны­ми ко­да­ми), ото­бра­зить толь­ко име­на фай­лов, вы­вес­ти контекст над и под най­ден­ны­ми стро­ка­ми или да­же все, что не со­ответ­ст­ву­ет ис­ко­мо­му.

Во-вто­рых, ес­ли вы су­мее­те от­вес­ти не­мно­го вре­ме­ни на изуче­ние ис­поль­зо­ва­ния ре­гу­ляр­ных вы­ра­же­ний, то ре­зуль­тат окупит­ся вде­ся­те­ро – то­гда-то мир grep дей­ст­ви­тель­но перед вами рас­кро­ет­ся.

По­че­му grep?

Сло­во ‘grep’ – со­кра­щение по пер­вым бу­к­вам стан­дарт­ной серии команд, ис­поль­зуе­мых в ed, од­ном из од­но­строч­ных тек­сто­вых ре­дак­то­ров Unix. Команды global/regular expression/print ве­лят ed по­ме­чать ка­ж­дую вход­ную стро­ку, со­от­вет­ствую­щую ре­гу­ляр­но­му вы­ра­жению (или шаб­ло­ну по­иска), и вы­во­дить ее на экран. Это при­ме­ня­лось так часто, что grep в Unix выне­с­ли в от­дель­ную ути­ли­ту. Ее исто­рия насчи­ты­ва­ет три де­ся­ти­ле­тия и несколь­ко различ­ных вер­сий и ал­го­рит­мов, и она все так же по­пу­ляр­на, как и при ро­ж­дении.

Че­ты­ре цен­ных шаб­ло­на

  1. Най­ти все стро­ки, со­дер­жа­щие сло­во ‘first’ и ‘1954’, в этом по­ряд­ке: grep -ri first.*1954 /usr/share/calendar
  2. Най­ти IP-ад­рес. Здесь на­до мно­го вво­дить, и точ­ность бу­дет не 100%, по­сколь­ку ре­зуль­тат вклю­чит, ска­жем, 9.9.9.9999, а это, ко­неч­но, ад­рес не­вер­ный. Мож­но на­пи­сать бо­лее стро­гий за­прос, но сни­же­ние ко­ли­че­ст­ва лож­ных сра­ба­ты­ва­ний не сто­ит уве­ли­че­ния слож­но­сти вы­ра­же­ния. grep -r ‘\([[:digit:]]\+\.\)\{3\}[[:digit:]]\+’ /etc/sysconfig/networkscripts
  3. Най­ти URL (вме­сто \.com под­ставь­те \.ru, и т. д.). Мы ука­за­ли обычный до­мен дли­ной от 3 до 50 сим­во­лов. grep -r ‘www\..\{3,50\}\.com’ /home/faye/.mozilla/
  4. На­ко­нец, вот две ко­ман­ды grep, свя­зан­ные вме­сте че­рез пе­ре­на­прав­ле­ние вы­во­да. В ре­зуль­та­те вы­во­дит­ся об­щее чис­ло сов­па­де­ний во всех фай­лах сра­зу, а не в ка­ж­дом по от­дель­но­сти: grep -riwh first /usr/share/calendar | grep -ic first
Персональные инструменты
купить
подписаться
Яндекс.Метрика