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
Kent

แน่ใจนะว่าเป็น-P? ฉันมีมัน
Kevin

4
@ เควินมันถูกลบใน 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ยังคงบอกว่า "สิ่งที่ต้องทำเพียงรายการเดียวคือการปรับปรุงประสิทธิภาพ" ใช่ time grep aa /usr/share/dict/words>/dev/nullใช้เวลาประมาณ 0.09 วินาทีด้วย grep ของ OS X และประมาณ 0.01 วินาทีด้วย GNU grep ใหม่ในการทำงานซ้ำ ๆ บน 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 ถ้า m {<loc> (. *) </loc>} 'sitemap.xml
Christian

2
@Christian ใช้เวลาเพียง 3 บรรทัดในการทำด้วยตัวแยกวิเคราะห์ XML ที่เหมาะสมเช่น XML :: LibXML (สายสำคัญ: say $_->textContent for $doc->findnodes('//loc');)
อิเคกามิ

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ไว้ด้านหน้าของเส้นทางของคุณ Brew ควรจะตั้งค่าที่ฉันเชื่อ? คุณใช้--default-names? อย่างไรก็ตามดีใจที่มันใช้งานได้ (: ไม่แน่ใจเกี่ยวกับการแฮ็กรอบ ๆ แต่ฉันคิดว่าระบบจุดเป็นสาเหตุหนึ่งที่ทำให้ไซต์นี้เป็นแหล่งข้อมูลที่ดี
drevicko

1
ใช่ฉันใช้ - ชื่อเริ่มต้นและการชง ไม่แน่ใจว่าการวาง / usr / local / bin ไว้ด้านหน้าเส้นทางของคุณดีกว่านามแฝงหรือไม่
pepper

10
อีกทางเลือกหนึ่ง--with-default-namesคือเพิ่มลงalias grep='ggrep'ในโปรไฟล์ทุบตีของคุณและปล่อยให้ผู้ผลิตเบียร์เก็บคำนำหน้าไว้
rymo

4
--with-default-namesถูกลบออกจากการชง ฉันได้ไปbrew install grepที่จะได้รับ ggrep แล้วทำตามที่ @rymo alias grep='ggrep'พูดและทำ
Henge

12

ติดตั้งackและใช้แทน Ack คือการแทนที่ grep ที่เขียนด้วย Perl มีการสนับสนุนอย่างเต็มที่สำหรับนิพจน์ทั่วไปของ Perl


ฉันต้องการตรวจสอบสิ่งนี้ แต่เป็นสำหรับคอมพิวเตอร์ที่ทำงานดังนั้นเราจึงไม่สามารถติดตั้งอะไรได้
kugyousha

@ironintention: ถ้าคุณสามารถติดตั้งโมดูล Perl ได้คุณก็ทำได้ดี แม้ว่าคุณจะไม่สามารถเพิ่มการติดตั้ง Perl ในเครื่องได้ แต่คุณสามารถใช้ local :: lib ได้ตลอดเวลา
Michael Carman

ackถูกออกแบบมาให้มีอยู่ในตัว คุณไม่จำเป็นต้องติดตั้งจริง หากคุณสามารถบันทึกไฟล์ได้ให้ทำเครื่องหมายว่า exectutable และอัปเดตPATHหากจำเป็นคุณก็พร้อมใช้งาน
tripleee

โปรดใช้ไวยากรณ์ ack ที่แทนที่ด้านบนได้ไหม
William Entriken

@FullDecent: เกือบจะเหมือนกัน: ack -o '(property:)\K.*\d+(?=end)' file.txt( -oหมายถึงสิ่งเดียวกัน แต่คุณไม่จำเป็นต้องใช้-Pกับ ack)
Michael Carman

11

OS X มีแนวโน้มที่จะให้ BSD มากกว่าเครื่องมือ GNU มันไม่มาพร้อมกับegrepแต่ที่น่าจะเป็นสิ่งที่คุณต้องดำเนินการค้นหา regex

ตัวอย่าง: egrep 'fo+b?r' foobarbaz.txt

ตัวอย่างจากหน้า OSX grep man:

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ไฟล์. ดังนั้นมันจะเข้ากันได้กับสคริปต์ของคุณ

สามารถติดตั้งกับ homebrew:

brew install pcre


Error: No available formula for pcregrep
Aaron Brager

GaborMarton ฉันแก้ไขคำตอบของคุณเพื่อรวมความคิดเห็นที่แก้ไขของ @Martin และต้องย้ายการจัดรูปแบบไปรอบ ๆ เพื่อให้ได้การเปลี่ยนแปลงขั้นต่ำ
Daniel Baird

3

แล้วการใช้ตัวเลือก '-E' ล่ะ? มันทำงานได้ดีสำหรับฉันยกตัวอย่างเช่นถ้าผมต้องการที่จะตรวจสอบหาphp_zip, php_xml, php_gd2ขยายจากPHP -mใช้ I:

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

ใช้ regex perl one-liner โดยส่ง find output ด้วยไปป์ ฉันใช้lookbehind (รับลิงก์srcใน html) และ lookahead for " และส่งเอาต์พุตของ 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.