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.