grep -P não funciona mais. Como posso reescrever minhas pesquisas?

102

Parece que a nova versão do OSX não oferece mais suporte grep -Pe, como tal, fez com que alguns dos meus scripts parassem de funcionar.

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

Eu preciso capturar o grep para uma variável e preciso usar as asserções de largura zero, bem como \K

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

Quaisquer alternativas seriam muito apreciadas.

kugyousha
fonte
8
que tal instalar gnu grep?
Kent
Tem certeza que é o -P? O meu tem.
Kevin
5
@Kevin Foi removido em 10.8.
Lri
8
@AdrianFrühwirth OS X greprealmente mudou de grep (GNU grep) 2.5.110,7 para grep (BSD grep) 2.5.1-FreeBSD10,8. Acho que foi por causa da GPL. O FreeBSD greptambém é baseado no GNU grepe ambas as versões grepsão de 2002. --labele -u/ --unix-byte-offetstambém foram removidos no 10.8. -z/ --decompress, -J/ --bz2decompress, --exclude-dir, --include-dir, -S, -O, E -pforam adicionados em 10,8. -Zmudou de --nullpara --decompress.
Lri
3
O FreeBSD grepque vem com o OS X é de 2002, e wiki.freebsd.org/BSDgrep ainda diz que "o único item TODO está melhorando o desempenho", então sim. time grep aa /usr/share/dict/words>/dev/nullleva cerca de 0,09 segundos com o grep do OS X e cerca de 0,01 segundos com um novo grep GNU em execuções repetidas no meu iMac.
Lri,

Respostas:

69

Se você quiser fazer o mínimo de trabalho, mude

grep -P 'PATTERN' file.txt

para

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

e mudar

grep -o -P 'PATTERN' file.txt

para

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

Então você obtém:

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`

Em seu caso específico, você pode obter um código mais simples com trabalho extra.

var1=`perl -nle'print for m{<st:italic>(.*)</italic>}g' file.txt`
var2=`perl -nle'print for /property:(.*\d+)end/g' file.txt`
ikegami
fonte
1
Isso funciona muito bem, mas retorna todas as correspondências, já que o grep que usei retornou apenas a primeira correspondência. alguma ideia sobre como devolver apenas o primeiro jogo?
kugyousha
1
@ironintention: adiciona | tail -1ao final do pipeline.
Peter
grepsempre retorna todas as linhas correspondentes (a menos que você use uma das opções onde não imprime nenhuma). De qualquer forma, if (/.../) { print $1; last; }fará com que ele imprima apenas a primeira correspondência.
ikegami
Eu usei isso para obter os urls de um mapa do site - obrigado amigo, não teria sobrevivido sem sua postagem! perl -nle'print $ 1 if m {<loc> (. *) </loc>} 'sitemap.xml
Cristão
2
@Christian, levaria apenas 3 linhas para fazer isso com um analisador XML adequado, como XML :: LibXML. (Linha Key: say $_->textContent for $doc->findnodes('//loc');)
Ikegami
97

Se seus scripts são apenas para seu uso, você pode instalar grepa partir de homebrew-coreusar brew:

brew install grep 

Então está disponível como ggrep(GNU grep). ele não substitui o sistema grep(você precisa colocar o grep instalado antes do do sistema no PATH).

A versão instalada por brewinclui a -Popção, então você não precisa alterar seus scripts.

Se precisar usar esses comandos com seus nomes normais, você pode adicionar um diretório "gnubin" ao seu PATH do bashrc como:

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

Você pode exportar esta linha em seu ~ / .bashrc ou ~ / .zshrc para mantê-la para novas sessões.

Veja aqui uma discussão sobre os prós e contras da --with-default-namesopção antiga e sua (recente) remoção.

drevicko
fonte
3
@pepper o que não funcionou? Provavelmente, o caminho não está definido corretamente - qual é o resultado which grep? Deve ser /usr/local/bin/grep. É um pouco malvado votar contra ele antes de verificar cuidadosamente se há um problema!
drevicko
2
provavelmente melhor adicionar /usr/local/binà frente de seu PATH. É suposto que Brew tenha feito isso, acredito? Você usou --default-names? De qualquer forma, fico feliz que funcione (: Não tenho certeza sobre como hackear, mas acho que o sistema de pontos é uma das razões pelas quais este site é um recurso tão bom.
drevicko
1
sim, usei --default-names e brew. Não tenho certeza se colocar / usr / local / bin na frente do seu caminho é melhor do que um alias, apenas uma alternativa
pimenta
10
uma alternativa --with-default-namesé adicionar alias grep='ggrep'ao seu perfil do bash e permitir que os brew dupes mantenham seus prefixos
rymo
4
--with-default-namesé removido da mistura. Tive brew install grepque obter o ggrep e fazer o que @rymo diz e faz alias grep='ggrep'.
Henge
13

Instale o ack e use-o em seu lugar. Ack é um substituto do grep escrito em Perl. Ele tem suporte total para expressões regulares Perl.

Michael Carman
fonte
Eu gostaria de verificar isso, mas isso é para computadores de trabalho, então não podemos instalar nada
kugyousha
@ironintention: Se você pode instalar módulos Perl, você está bem. Mesmo se você não puder adicionar à instalação local do Perl, você sempre pode usar local :: lib.
Michael Carman
acké projetado para ser independente; você não precisa realmente instalá-lo. Se você puder salvar um arquivo, marcá-lo como executável e atualizá- PATHlo, se necessário, você está pronto para prosseguir.
tripleee
Você pode agradar a sintaxe ack que substitui a acima
William Entriken
@FullDecent: É quase idêntico: ack -o '(property:)\K.*\d+(?=end)' file.txt( -osignifica a mesma coisa, mas você não precisa do -Pcom ack)
Michael Carman
11

OS X tende a fornecer ferramentas BSD em vez de ferramentas GNU. Ele não vêm comegrep entanto, , o que provavelmente é tudo que você precisa para realizar pesquisas regex.

exemplo: egrep 'fo+b?r' foobarbaz.txt

Um snippet da página de manual do OSX grep:

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

nebuloso
fonte
6
A invocação direta como egrep está obsoleta. A mesma capacidade também está disponível como grep -E. É ... uma triste sombra do Perl, sem afirmações aparentes, a maioria das fugas de barra invertida, opções, condicionais, etc :( Usuários avançados irão odiar, mas pelo menos faz o trabalho.
Dewi Morgan,
1
Obrigado. grep -Eem vez de grep -Pera exatamente o que eu precisava.
asmaier
6

use perl;

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

Se você precisar de mais grepopções (vejo que você gostaria -opelo menos), existem várias pgrepimplementações flutuando pela rede, muitas delas em Perl.

Se "quase Perl" for bom o suficiente, o PCRE vem com pcregrep.

triplo
fonte
5

Há uma outra alternativa: pcregrep.

Pcregrep é um grep com expressões regulares compatíveis com Perl. Ele tem exatamente o mesmo uso que grep -P. Portanto, será compatível com seus scripts.

Pode ser instalado com homebrew:

brew install pcre

Gabor Marton
fonte
Error: No available formula for pcregrep
Aaron Brager,
GaborMarton, editei sua resposta para incluir o comentário de correção de @Martin e tive que mudar um pouco a formatação para superar as alterações mínimas.
Daniel Baird
3

Que tal usar a opção '-E'? Ele funciona muito bem para mim, por exemplo, se eu quiser verificar se há uma php_zip, php_xml, php_gd2extensão de php -m uso I:

php -m | grep -E '(zip|xml|gd2)'
ZenC
fonte
1
isso funciona. Mac usa FreeBSD grep e Linux usa GNU grep ... então essa correção funcionou no meu macOS sierra
jimh
2

Equivalente à resposta aceita, mas sem a exigência da chave -P, que não estava presente nas duas máquinas que eu tinha disponível.

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

Este funcionou para mim:

    awk  -F":" '/PATTERN/' file.txt
petegam
fonte
0

Outra solução Perl para -P

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

use o regex perl one-liner passando a saída find com um pipe. Usei lookbehind (obter links src em html) e lookahead para " e passei a saída de curl (html) para ele.

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
fonte