grep -P不再起作用。如何重写搜索?


96

看起来新版本的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ühwirthOS Xgrep实际上从grep (GNU grep) 2.5.110.7更改为grep (BSD grep) 2.5.1-FreeBSD10.8。我想这是因为GPL。FreeBSDgrep也是基于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 2014年

3
grepOS X附带的FreeBSD是2002年发行的,而wiki.freebsd.org/BSDgrep仍然说“唯一的TODO项是提高性能”,是的。time grep aa /usr/share/dict/words>/dev/null在iMac上反复运行时,使用OS X的grep大约需要0.09秒,而使用新的GNU grep大约需要0.01秒。
Lri 2014年

Answers:


66

如果您要进行最少的工作,请更改

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 2013年

我用它来获取站点地图的网址-谢谢队友,如果没有您的发帖,您将一无所获!perl -nle'print $ 1 if m {<loc>(。*)</ loc>}'sitemap.xml
Christian

2
@Christian,只需要3行就可以使用适当的XML解析器(例如XML :: LibXML)来完成此操作。(关键行:say $_->textContent for $doc->findnodes('//loc');
ikegami 2013年

92

如果你的脚本仅供您使用,您可以安装grephomebrew-core使用brew

brew install grep 

然后可以作为ggrep(GNU grep)使用。它不会取代系统grep(您需要将已安装的grep放在系统上的grep之前PATH)。

安装的版本 brew包括-P选项,因此您无需更改脚本。

如果需要使用这些命令的常规名称,则可以从bashrc将“ gnubin”目录添加到PATH中,例如:

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

您可以在〜/ .bashrc或〜/ .zshrc上导出此行,以使其保留用于新会话。

请看这里以了解有关旧--with-default-names选项及其(最近)删除的优缺点的讨论。


3
@pepper什么不起作用?可能路径设置不正确-输出是which grep什么?应该是/usr/local/bin/grep。在仔细检查是否有问题之前,请稍加投票!
drevicko 2014年

2
最好将其添加/usr/local/bin到PATH的前面。我相信布鲁尔应该设置这个吗?你用了--default-names吗?无论如何,很高兴它的工作原理(:不知道有关它周围黑客攻击,但我认为这一点是系统的原因之一,这个网站是这么好的资源。
drevicko

1
是的,我确实使用了--default-names和brew。不知道将/ usr / local / bin放在路径的前面是否比别名更好,只是一个替代方法
Pepper

10
另一种方法--with-default-names是添加alias grep='ggrep'到您的bash个人资料中,让酿造的
假人

4
--with-default-names从酿造中取出。我必须先brew install grep获取ggrep,然后按照@rymo的说明进行操作alias grep='ggrep'
Henge

12

安装ack并改用它。Ack是用Perl编写的grep替代品。它完全支持Perl正则表达式。


我想检查一下,但这是用于
办公

@ironintention:如果可以安装Perl模块,那就很好。即使您不能添加到本地Perl安装中,也可以始终使用local :: lib。
迈克尔·卡曼

ack设计成独立的;您不需要实际安装它。如果您可以保存文件,将其标记为可执行文件,并PATH在必要时进行更新,则一切顺利。
2014年

可以请你的ACK语法替换上面
威廉Entriken

@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悲伤的阴影,缺乏环视断言,大部分反斜杠逃逸的,选项,条件等:(电力用户会讨厌它,但它至少做的工作。
黛维摩根

1
谢谢。grep -E而不是grep -P我真正需要的。
asmaier19年

6

use perl;

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

如果您需要更多grep选择(我-o至少希望看到),可以使用多种选择pgrep网上实现,其中许多是在Perl中实现的。

如果“ almost Perl”足够好,则PCRE附带pcregrep


5

还有另一种选择:pcregrep

Pcregrep是具有与Perl兼容的正则表达式的grep。与的用法完全相同grep -P。因此它将与您的脚本兼容。

可以通过自制软件安装:

brew install pcre


Error: No available formula for pcregrep
亚伦·布拉格

GaborMarton,我编辑了您的答案以包括@Martin的更正注释,并且不得不稍微调整一下格式以克服最小的更改。
丹尼尔·贝尔德

3

如何使用“ -E”选项?它工作正常的我来说吧,如果我要来检查php_zipphp_xmlphp_gd2扩展从PHP -m我使用:

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

1
这可行。Mac使用FreeBSD grep,而Linux使用GNU grep ...所以此修复程序适用于我的macOS sierra
jimh,2010年

2

等效于已接受的答案,但没有-P开关的要求,这在我可用的两台机器上都不存在。

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

2

这个为我工作:

    awk  -F":" '/PATTERN/' file.txt

0

另一种-P的Perl解决方案

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

0

通过将find输出与管道传递来使用perl单线正则表达式。我使用了lookbehind(在html中获取src链接)和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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.