grep -P більше не працює. Як я можу переписати свої пошукові запити?


99

Схоже, нова версія OSX більше не підтримує, grep -Pі як така деякі мої сценарії перестали працювати.

var1=`grep -o -P '(?<=<st:italic>).*(?=</italic>)' file.txt`

Мені потрібно захопити grep у змінну, і мені також потрібно використовувати твердження про нульову ширину \K

var2=`grep -P -o '(property:)\K.*\d+(?=end)' file.txt`

Будемо вдячні за будь-які альтернативи.


8
як щодо установки gnu grep?
Кент,

Ви впевнені, що це -P? У мого це є.
Кевін,

4
@Kevin Його було видалено в 10.8.
Lri

8
@ AdrianFrühwirth OS X grepнасправді змінився з grep (GNU grep) 2.5.110.7 на grep (BSD grep) 2.5.1-FreeBSD10.8. Я думаю, це було через GPL. FreeBSD grepтакож базується на GNU, grepі обидві версії grepвід 2002 р. --labelТа -u/ --unix-byte-offetsтакож були вилучені в 10.8. -z/ --decompress, -J/ --bz2decompress, --exclude-dir, --include-dir, -S, -O, І -pбули додані в 10,8. -Zзмінено з --nullна --decompress.
Lri

3
FreeBSD, grepякий постачається з OS X, походить з 2002 року, і wiki.freebsd.org/BSDgrep все ще каже, що "єдиним елементом TODO є підвищення продуктивності", так що так. time grep aa /usr/share/dict/words>/dev/nullзаймає близько 0,09 секунди з grep OS X та близько 0,01 секунди з новим grep GNU при повторних прогонах на моєму iMac.
Lri

Відповіді:


68

Якщо ви хочете виконати мінімальний обсяг роботи, змініть

grep -P 'PATTERN' file.txt

до

perl -nle'print if m{PATTERN}' file.txt

і зміни

grep -o -P 'PATTERN' file.txt

до

perl -nle'print $& while m{PATTERN}g' file.txt

Отже, ви отримуєте:

var1=`perl -nle'print $& while m{(?<=<st:italic>).*(?=</italic>)}g' file.txt`
var2=`perl -nle'print $& while m{(property:)\K.*\d+(?=end)}g' file.txt`

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

var1=`perl -nle'print for m{<st:italic>(.*)</italic>}g' file.txt`
var2=`perl -nle'print for /property:(.*\d+)end/g' file.txt`

1
Це чудово працює, але повертає всі збіги, оскільки grep, який я використовував, повертав лише перший збіг. будь-яка ідея про те, як повернути лише перший матч?
kugyousha

1
@ironintention: додати | tail -1до кінця конвеєра.
Петро

grepзавжди повертає всі відповідні рядки (якщо ви не використовуєте одну з опцій, де вона взагалі не друкує). У будь-якому випадку, if (/.../) { print $1; last; }це змусить друкувати лише першу відповідність.
ikegami

Я використав це, щоб отримати URL-адреси мапи сайту - дякую, товаришу, не встиг би без вашого допису! perl -nle'print $ 1 if m {<loc> (. *) </loc>} 'sitemap.xml
Christian

2
@Christian, знадобиться лише 3 рядки, щоб зробити це за допомогою відповідного аналізатора XML, такого як XML :: LibXML. (Key лінія: say $_->textContent for $doc->findnodes('//loc');)
Ikegami

93

Якщо ваші скрипти тільки для особистого використання, ви можете встановити grepз homebrew-coreдопомогою brew:

brew install grep 

Тоді він доступний як ggrep(GNU grep). він не замінює систему grep(вам потрібно поставити встановлений grep перед системним на PATH).

Версія, встановлена ​​користувачем, brewвключає цю -Pопцію, тому вам не потрібно змінювати сценарії.

Якщо вам потрібно використовувати ці команди з їх звичайними іменами, ви можете додати каталог "gnubin" до вашого PATH з вашого bashrc, наприклад:

PATH="/usr/local/opt/grep/libexec/gnubin:$PATH"

Ви можете експортувати цей рядок на ~ / .bashrc або ~ / .zshrc, щоб зберегти його для нових сеансів.

Будь ласка, дивіться тут для обговорення плюсів і мінусів старого --with-default-namesваріанту та його (недавнього) видалення.


3
@pepper що не працювало? Швидше за все, шлях встановлений неправильно - який результат which grep? Має бути /usr/local/bin/grep. Це; трохи негідне голосувати, перш ніж уважно перевірити, чи є проблема!
drevicko

2
можливо, краще додати /usr/local/binдо передньої частини вашого ШЛЯХУ. Брю повинен встановити це, я вірю? Ви користувались --default-names? У будь-якому випадку, радий, що це працює (: Не впевнений у злому навколо нього, але я думаю, що система балів є однією з причин, чому цей сайт є таким хорошим ресурсом.
drevicko

1
так, я використовував --default-names і brew. Не впевнений, що розміщення / usr / local / bin перед вашим шляхом краще, ніж псевдонім, просто альтернатива
перець

10
альтернативою --with-default-namesє додавання alias grep='ggrep'до вашого профілю bash і дозволяти
вареним дуп’якам

4
--with-default-namesвидаляється із заварки. Мені довелося brew install grepотримати ggrep, а потім зробити те, що каже і робить @rymo alias grep='ggrep'.
Хенге

12

Встановіть ack і використовуйте його замість цього. Ack - це заміна grep, написана на Perl. Він має повну підтримку регулярних виразів Perl.


Я хотів би це перевірити, але це для робочих комп’ютерів, тому ми не можемо нічого встановити
kugyousha

@ironintention: Якщо ви можете встановити модулі Perl, ви добре. Навіть якщо ви не можете додати до локальної інсталяції Perl, ви завжди можете використовувати local :: lib.
Майкл Карман

ackрозроблений для автономності; вам не потрібно фактично встановлювати його. Якщо ви можете зберегти файл, позначити його як виконуваний та оновити свій, PATHякщо потрібно, ви готові піти.
триплеє 02.03.14

Чи можете ви, будь ласка, синтаксис ack, який замінює наведене
Вільям Ентрікен

@FullDecent: Це майже ідентично: ack -o '(property:)\K.*\d+(?=end)' file.txt( -oозначає одне і те ж, але -Pз ack вам не потрібно )
Майкл Карман

11

OS X має тенденцію надавати BSD, а не інструменти GNU. Він дійсно прийшов з egrepтим НЕ менш, що, ймовірно , все , що потрібно для виконання регулярних виразів пошуку.

приклад: egrep 'fo+b?r' foobarbaz.txt

Фрагмент зі сторінки користувача OSX grep:

grep is used for simple patterns and basic regular expressions (BREs); egrep can handle extended regular expressions (EREs).


5
Пряме виклик, оскільки egrep застаріло. Доступна та ж здатність, що і grep -E. Це ... сумна тінь Perl, у якій відсутні твердження про перегляд, більшість втік зворотних рисок, опцій, умовних умов тощо: (Потужні користувачі будуть це ненавидіти, але це, принаймні, робить цю роботу.
Dewi Morgan,

1
Дякую. grep -Eа grep -Pне саме те, що мені потрібно.
asmaier

6

use perl;

perl -ne 'print if /regex/' files ...

Якщо вам потрібні більше grepопцій (я бачу, що ви хотіли б -oпринаймні), існують різні pgrepреалізації, що плавають по мережі, багато з них у Perl.

Якщо "майже Perl" достатньо хороший, PCRE постачається з pcregrep.


5

Існує ще одна альтернатива: pcregrep.

Pcregrep - це grep із регулярними виразами, сумісними з Perl. Він має точно таке ж використання, як grep -P. Тож він буде сумісний з вашими сценаріями.

Його можна встановити за допомогою домашньої писемності:

brew install pcre


Error: No available formula for pcregrep
Аарон Брагер

GaborMarton, я відредагував вашу відповідь, включивши виправлений коментар @Martin, і мені довелося трохи перемістити форматування, щоб подолати мінімальні зміни.
Даніель Бейрд,

3

Як щодо використання опції '-E'? Він відмінно працює для мене, наприклад, якщо я хочу перевірити для php_zip, php_xml, php_gd2розширення з PHP -m я використовую:

php -m | grep -E '(zip|xml|gd2)'

1
це працює. Mac використовує FreeBSD grep, а Linux використовує GNU grep ... тому це виправлення спрацювало на моєму macOS Sierra
jimh

2

Еквівалент прийнятої відповіді, але без вимоги перемикача -P, якого не було на обох машинах, які я мав у наявності.

find . -type f -exec perl -nle 'print $& if m{\r\n}' {} ';' -exec perl -pi -e 's/\r\n/\n/g' {} '+'



0

використовуйте регулярний вираз perl для одного вкладиша, передаючи вихідний результат пошуку трубою. Я використав lookbehind (отримати посилання src у html) та lookahead для " і передав йому висновок curl (html).

bash-3.2# curl stackoverflow.com | perl -0777 -ne '$a=1;while(m/(?<=src\=\")(.*)(?=\")/g){print "Match #".$a." "."$&\n";$a+=1;}'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  239k  100  239k    0     0  1911k      0 --:--:-- --:--:-- --:--:-- 1919k
Match #1 //ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js
Match #2 //cdn.sstatic.net/Js/stub.en.js?v=fb6157e02696
Match #3 https://ssum-sec.casalemedia.com/usermatch?s=183712&amp;cb=https%3A%2F%2Fengine.adzerk.net%2Fudb%2F22%2Fsync%2Fi.gif%3FpartnerId%3D1%26userId%3D
Match #4 //i.stack.imgur.com/817gJ.png" height="16" width="18" alt="" class="sponsor-tag-img">elasticsearch</a> <a href="/questions/tagged/elasticsearch-2.0" class="post-tag" title="show questions tagged &#39;elasticsearch-2.0&#39;" rel="tag">elasticsearch-2.0</a> <a href="/questions/tagged/elasticsearch-dsl" class="post-tag" title="show questions tagged &#39;elasticsearch-dsl&#39;" rel="tag
Match #5 //i.stack.imgur.com/817gJ.png" height="16" width="18" alt="" class="sponsor-tag-img">elasticsearch</a> <a href="/questions/tagged/sharding" class="post-tag" title="show questions tagged &#39;sharding&#39;" rel="tag">sharding</a> <a href="/questions/tagged/master" class="post-tag" title="show questions tagged &#39;master&#39;" rel="tag
Match #6 //i.stack.imgur.com/tKsDb.png" height="16" width="18" alt="" class="sponsor-tag-img">android</a> <a href="/questions/tagged/linux" class="post-tag" title="show questions tagged &#39;linux&#39;" rel="tag">linux</a> <a href="/questions/tagged/camera" class="post-tag" title="show questions tagged &#39;camera&#39;" rel="tag
Match #7 //i.stack.imgur.com/tKsDb.png" height="16" width="18" alt="" class="sponsor-tag-img">android</a> <a href="/questions/tagged/firebase" class="post-tag" title="show questions tagged &#39;firebase&#39;" rel="tag"><img src="//i.stack.imgur.com/5d55j.png" height="16" width="18" alt="" class="sponsor-tag-img">firebase</a> <a href="/questions/tagged/firebase-authentication" class="post-tag" title="show questions tagged &#39;firebase-authentication&#39;" rel="tag
Match #8 //i.stack.imgur.com/tKsDb.png" height="16" width="18" alt="" class="sponsor-tag-img">android</a> <a href="/questions/tagged/ios" class="post-tag" title="show questions tagged &#39;ios&#39;" rel="tag">ios</a> <a href="/questions/tagged/in-app-purchase" class="post-tag" title="show questions tagged &#39;in-app-purchase&#39;" rel="tag">in-app-purchase</a> <a href="/questions/tagged/piracy-protection" class="post-tag" title="show questions tagged &#39;piracy-protection&#39;" rel="tag
Match #9 //i.stack.imgur.com/tKsDb.png" height="16" width="18" alt="" class="sponsor-tag-img">android</a> <a href="/questions/tagged/unity3d" class="post-tag" title="show questions tagged &#39;unity3d&#39;" rel="tag">unity3d</a> <a href="/questions/tagged/vr" class="post-tag" title="show questions tagged &#39;vr&#39;" rel="tag
Match #10 http://pixel.quantserve.com/pixel/p-c1rF4kxgLUzNc.gif" alt="" class="dno
bash-3.2# date
Mon Oct 24 20:57:11 EDT 2016
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.