grep -P już nie działa. Jak mogę przepisać moje wyszukiwania?

102

Wygląda na to, że nowa wersja OSX nie obsługuje już grep -Pi w związku z tym niektóre z moich skryptów przestały działać.

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

Muszę przechwycić grep do zmiennej i muszę użyć asercji o zerowej szerokości, jak również \K

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

Wszelkie alternatywy byłyby bardzo mile widziane.

kugyousha
źródło
8
co powiesz na zainstalowanie gnu grep?
Kent
Czy na pewno to -P? Mój to ma.
Kevin
5
@Kevin Został usunięty w 10.8.
Lri
9
@ AdrianFrühwirth OS X grepfaktycznie zmienił się z grep (GNU grep) 2.5.110.7 do grep (BSD grep) 2.5.1-FreeBSD10.8. Myślę, że to z powodu GPL. FreeBSD grepjest również oparte na GNU grepi obie wersje greppochodzą z 2002 roku --labeli -u/ --unix-byte-offetszostały również usunięte w 10.8. -z/ --decompress, -J/ --bz2decompress, --exclude-dir, --include-dir, -S, -O, I -pdodano 10,8. -Zzmieniono z --nullna --decompress.
Lri
3
FreeBSD, grepktóre jest dostarczane z OS X pochodzi z 2002 roku, a wiki.freebsd.org/BSDgrep nadal mówi, że „jedyna pozycja TODO poprawia wydajność”, więc tak. time grep aa /usr/share/dict/words>/dev/nullzajmuje około 0,09 sekundy w przypadku programu grep w systemie OS X i około 0,01 sekundy w przypadku nowego programu GNU grep przy powtarzających się uruchomieniach na moim iMacu.
Lri

Odpowiedzi:

69

Jeśli chcesz wykonać minimalną ilość pracy, zmień

grep -P 'PATTERN' file.txt

do

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

i zmienić

grep -o -P 'PATTERN' file.txt

do

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

Otrzymujesz więc:

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`

W twoim konkretnym przypadku możesz uzyskać prostszy kod przy dodatkowej pracy.

var1=`perl -nle'print for m{<st:italic>(.*)</italic>}g' file.txt`
var2=`perl -nle'print for /property:(.*\d+)end/g' file.txt`
ikegami
źródło
1
Działa to świetnie, ale zwraca wszystkie dopasowania, ponieważ grep, którego użyłem, zwrócił tylko pierwsze dopasowanie. masz pomysł, jak zwrócić tylko pierwsze dopasowanie?
kugyousha
1
@ironintention: dodaj | tail -1na końcu potoku.
Peter
grepzawsze zwraca wszystkie pasujące wiersze (chyba że używasz jednej z opcji, w których w ogóle nie wyświetla żadnego). W każdym razie if (/.../) { print $1; last; }spowoduje to wydrukowanie tylko pierwszego dopasowania.
ikegami
Użyłem tego, aby uzyskać adresy URL mapy witryny - dzięki kolego, nie zrobiłbym tego bez Twojego posta! perl -nle'print $ 1 if m {<loc> (. *) </loc>} 'sitemap.xml
Christian
2
@Christian, zajęłoby to tylko 3 linie przy użyciu odpowiedniego parsera XML, takiego jak XML :: LibXML. (Key linia: say $_->textContent for $doc->findnodes('//loc');)
Ikegami
97

Jeśli Twoje skrypty są przeznaczone tylko do Twojego użytku, możesz zainstalować grepje homebrew-coreza pomocą brew:

brew install grep 

Wtedy jest dostępny jako ggrep(GNU grep). nie zastępuje systemu grep(musisz umieścić zainstalowany grep przed systemem PATH).

Wersja zainstalowana przez brewzawiera -Popcję, więc nie musisz zmieniać swoich skryptów.

Jeśli potrzebujesz użyć tych poleceń z ich normalnymi nazwami, możesz dodać katalog „gnubin” do swojej PATH z poziomu bashrc, na przykład:

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

Możesz wyeksportować tę linię do swojego ~ / .bashrc lub ~ / .zshrc, aby zachować ją dla nowych sesji.

Proszę zobaczyć tutaj, aby omówić zalety i wady starej --with-default-namesopcji oraz jej (niedawnego) usunięcia.

drevicko
źródło
3
@pepper co nie zadziałało? Prawdopodobnie ścieżka nie jest ustawiona prawidłowo - jakie są wyniki which grep? Powinien być /usr/local/bin/grep. Jest to trochę trudne do zagłosowania, zanim dokładnie sprawdzisz, czy jest problem!
drevicko
2
prawdopodobnie lepiej dodać /usr/local/binna początku ścieżki PATH. Wierzę, że Brew ma to ustawić? Czy używałeś --default-names? W każdym razie cieszę się, że to działa (: Nie jestem pewien co do hakowania wokół niego, ale myślę, że system punktów jest jednym z powodów, dla których ta strona jest tak dobrym źródłem.
drevicko
1
tak, użyłem --default-names i brew. Nie jestem pewien, czy umieszczenie / usr / local / bin na początku ścieżki jest lepsze niż alias, tylko alternatywa
pieprz
10
alternatywą dla tego --with-default-namesjest dodanie alias grep='ggrep'do profilu basha i pozwolenie
napastnikom
4
--with-default-namesjest usuwany z naparu. Musiałem brew install grepzdobyć ggrep, a następnie zrobić to, co mówi @rymo alias grep='ggrep'.
Henge
13

Zainstaluj ACK i używaj go zamiast tego. Ack to zamiennik grepa napisany w Perlu. Posiada pełne wsparcie dla wyrażeń regularnych Perla.

Michael Carman
źródło
Chciałbym to sprawdzić, ale to dotyczy komputerów roboczych, więc nie możemy niczego zainstalować
kugyousha
@ironintention: Jeśli możesz zainstalować moduły Perla, jesteś dobry. Nawet jeśli nie możesz dodać do lokalnej instalacji Perla, zawsze możesz użyć local :: lib.
Michael Carman
ackjest zaprojektowany jako samodzielny; nie musisz go faktycznie instalować. Jeśli możesz zapisać plik, oznaczyć go jako możliwy do wykonania i zaktualizować w PATHrazie potrzeby, możesz zaczynać .
tripleee
Czy możesz podać składnię ACK, która zastępuje powyższe
William Entriken
@FullDecent: Jest prawie identyczny: ack -o '(property:)\K.*\d+(?=end)' file.txt( -ooznacza to samo, ale nie potrzebujesz potwierdzenia -P)
Michael Carman
11

OS X dostarcza raczej narzędzi BSD niż GNU. To nie dysponują egrepjednak, co jest chyba wszystko, co trzeba wykonać regex wyszukiwania.

przykład: egrep 'fo+b?r' foobarbaz.txt

Fragment ze strony podręcznika grep dla systemu OSX:

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

mglisty
źródło
6
Bezpośrednie wywołanie, ponieważ egrep jest przestarzałe. Ta sama zdolność jest również dostępna jako grep -E. To ... smutny cień Perla, pozbawiony asercji do obejścia, większości ukośników odwrotnych, opcji, warunków itp. :( Zaawansowani użytkownicy go nienawidzą, ale przynajmniej spełnia swoje zadanie.
Dewi Morgan
1
Dzięki. grep -Ezamiast tego grep -Pbył dokładnie tym, czego potrzebowałem.
asmaier
6

use perl;

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

Jeśli potrzebujesz więcej grepopcji (widzę, że chciałbyś -oprzynajmniej), pgrepw sieci krążą różne implementacje, z których wiele jest w Perlu.

Jeśli „prawie Perl” jest wystarczająco dobre, PCRE jest dostarczane z pcregrep.

tripleee
źródło
5

Jest jeszcze inna alternatywa: pcregrep.

Pcregrep to grep z wyrażeniami regularnymi kompatybilnymi z Perl. Ma dokładnie takie samo zastosowanie jak grep -P. Więc będzie kompatybilny z twoimi skryptami.

Można go zainstalować za pomocą homebrew:

brew install pcre

Gabor Marton
źródło
Error: No available formula for pcregrep
Aaron Brager
GaborMarton, zredagowałem twoją odpowiedź tak, aby zawierała poprawiający komentarz @Martina i musiałem trochę przesunąć formatowanie, aby obejść minimalne zmiany.
Daniel Baird
3

Co powiesz na użycie opcji „-E”? Działa to dobrze dla mnie, na przykład, jeśli chcę, aby sprawdzić, czy php_zip, php_xml, php_gd2rozszerzenie z php -m używam:

php -m | grep -E '(zip|xml|gd2)'
ZenC
źródło
1
to działa. Mac używa FreeBSD grep, a Linux używa GNU grep ... więc ta poprawka działała na moim macOS Sierra
jimh
2

Odpowiednik zaakceptowanej odpowiedzi, ale bez wymogu przełącznika -P, którego nie było na obu komputerach, które miałem do dyspozycji.

find . -type f -exec perl -nle 'print $& if m{\r\n}' {} ';' -exec perl -pi -e 's/\r\n/\n/g' {} '+'
nuzzolilo
źródło
2

Ten pracował dla mnie:

    awk  -F":" '/PATTERN/' file.txt
petegam
źródło
0

Kolejne rozwiązanie Perla dla -P

var1=$( perl -ne 'print $1 if m#<st:italic>([^<]+)</st:italic># ' file.txt)
Rory Hunter
źródło
0

użyj jednowierszowego wyrażenia regularnego perl, przekazując wynik wyszukiwania potokiem. Użyłem lookbehind (pobierz linki src w html) i lookahead dla i przekazałem do niego wynik 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
Rohit Malgaonkar
źródło