grep -P không còn hoạt động. Làm cách nào để viết lại các tìm kiếm của tôi?


98

Có vẻ như phiên bản OSX mới không còn hỗ trợ grep -Pvà do đó, một số tập lệnh của tôi ngừng hoạt động.

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

Tôi cần nắm bắt grep vào một biến và tôi cần sử dụng xác nhận chiều rộng bằng không, cũng như \K

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

Bất kỳ lựa chọn thay thế sẽ được đánh giá rất cao.


8
làm thế nào về cài đặt gnu grep?
Kent

Bạn có chắc đó là -P? Của tôi có nó.
Kevin

4
@Kevin Nó đã bị xóa vào 10.8.
Lri

8
@ AdrianFrühwirth OS X grepthực sự đã thay đổi từ grep (GNU grep) 2.5.110.7 thành grep (BSD grep) 2.5.1-FreeBSD10.8. Tôi đoán đó là vì GPL. FreeBSD grepcũng dựa trên GNU grepvà cả hai phiên bản grepđều có từ năm 2002. --label-u/ --unix-byte-offetscũng đã bị gỡ bỏ trong 10.8. -z/ --decompress, -J/ --bz2decompress, --exclude-dir, --include-dir, -S, -O, Và -pđược thêm vào trong 10,8. -Zđã thay đổi từ --nullthành --decompress.
Lri

3
FreeBSD grepđi kèm với OS X có từ năm 2002, và wiki.freebsd.org/BSDgrep vẫn nói rằng "mục TODO duy nhất đang cải thiện hiệu suất", đúng vậy. time grep aa /usr/share/dict/words>/dev/nullmất khoảng 0,09 giây với grep của OS X và khoảng 0,01 giây với grep GNU mới khi chạy lặp lại trên iMac của tôi.
Lri

Câu trả lời:


68

Nếu bạn muốn làm số lượng công việc tối thiểu, hãy thay đổi

grep -P 'PATTERN' file.txt

đến

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

và thay đổi

grep -o -P 'PATTERN' file.txt

đến

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

Vì vậy, bạn nhận đượ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`

Trong trường hợp cụ thể của bạn, bạn có thể đạt được mã đơn giản hơn với công việc bổ sung.

var1=`perl -nle'print for m{<st:italic>(.*)</italic>}g' file.txt`
var2=`perl -nle'print for /property:(.*\d+)end/g' file.txt`

1
Điều này hoạt động tốt nhưng nó trả về tất cả các trận đấu như nơi mà grep tôi đã sử dụng chỉ trả lại trận đấu đầu tiên. bất kỳ ý tưởng nào về cách quay lại trận đấu đầu tiên?
kugyousha

1
@ironintention: thêm | tail -1vào cuối đường ống.
Peter

grepluôn trả về tất cả các dòng phù hợp (trừ khi bạn sử dụng một trong các tùy chọn mà nó không in ra). Dù sao, if (/.../) { print $1; last; }nó sẽ khiến nó chỉ in trận đầu tiên.
ikegami

Tôi đã sử dụng điều này để lấy ra các url của sơ đồ trang web - cảm ơn người bạn đời, sẽ không tạo được nếu không có bài đăng của bạn! perl -nle'print $ 1 if m {<loc> (. *) </loc>} 'sitemap.xml
Christian

2
@Christian, Chỉ mất 3 dòng để làm điều đó với một trình phân tích cú pháp XML thích hợp như XML :: LibXML. (Dòng chính say $_->textContent for $doc->findnodes('//loc');:)
ikegami

92

Nếu kịch bản của bạn là dành cho chỉ sử dụng, bạn có thể cài đặt greptừ homebrew-coresử dụng brew:

brew install grep 

Sau đó, nó có sẵn dưới dạng ggrep(GNU grep). nó không thay thế hệ thống grep(bạn cần đặt grep đã cài đặt trước hệ thống trên PATH).

Phiên bản được cài đặt bởi brewbao gồm -Ptùy chọn, vì vậy bạn không cần phải thay đổi tập lệnh của mình.

Nếu bạn cần sử dụng các lệnh này với tên thông thường của chúng, bạn có thể thêm thư mục "gnubin" vào PATH từ bashrc của bạn như:

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

Bạn có thể xuất dòng này trên ~ / .bashrc hoặc ~ / .zshrc của bạn để giữ nó cho các phiên mới.

Vui lòng xem tại đây để thảo luận về ưu và nhược điểm của --with-default-namestùy chọn cũ và tùy chọn bị xóa (gần đây).


3
@pepper cái gì không hoạt động? Có thể đường dẫn không được đặt đúng cách - đầu ra là which grepgì? Nên /usr/local/bin/grep. Nó; một chút có nghĩa là để phản đối trước khi bạn kiểm tra cẩn thận rằng có vấn đề!
drevicko

2
có lẽ tốt hơn để thêm /usr/local/binvào phía trước PATH của bạn. Tôi tin rằng Brew sẽ thiết lập điều đó? Bạn đã sử dụng --default-names? Dù sao, rất vui vì nó hoạt động (: Không chắc chắn về việc hack xung quanh nó, nhưng tôi nghĩ hệ thống điểm là một trong những lý do khiến trang web này là một nguồn tài nguyên tốt.
drevicko

1
vâng, tôi đã sử dụng - tên mặc định và pha chế. Không chắc liệu việc đặt / usr / local / bin ở phía trước đường dẫn của bạn có tốt hơn bí danh hay không, chỉ là một sự thay thế
tiêu

10
một thay thế cho --with-default-nameslà để thêm alias grep='ggrep'vào hồ sơ bash bạn và để giá trị nhân bản brew giữ tiền tố của họ
rymo

4
--with-default-namesđược loại bỏ khỏi bia. Tôi phải brew install greptải ggrep và sau đó làm như @rymo nói và làm alias grep='ggrep'.
Henge

12

Cài đặt ack và sử dụng nó thay thế. Ack là một thay thế grep được viết bằng Perl. Nó có hỗ trợ đầy đủ cho các biểu thức chính quy Perl.


Tôi muốn kiểm tra điều này nhưng đây là dành cho máy tính làm việc nên chúng tôi không thể cài đặt bất kỳ thứ gì
kugyousha 22/05

@ironintention: Nếu bạn có thể cài đặt các mô-đun Perl, bạn tốt. Ngay cả khi bạn không thể thêm vào cài đặt Perl cục bộ, bạn luôn có thể sử dụng local :: lib.
Michael Carman

ackđược thiết kế khép kín; bạn không cần thực sự cài đặt nó. Nếu bạn có thể lưu một tệp, hãy đánh dấu tệp đó là có thể phát hiện và cập nhật tệp PATHnếu cần, bạn đã sẵn sàng.
tripleee

Bạn có thể làm hài lòng những cú pháp ack thay thế ở trên
William Entriken

@FullDecent: Nó gần như giống hệt nhau: ack -o '(property:)\K.*\d+(?=end)' file.txt( -ocó nghĩa là giống nhau, nhưng bạn không cần -Pvới ack)
Michael Carman

11

OS X có xu hướng cung cấp BSD hơn là các công cụ GNU. Tuy nhiên, nó kèm theo egrep, đó có lẽ là tất cả những gì bạn cần để thực hiện tìm kiếm regex.

thí dụ: egrep 'fo+b?r' foobarbaz.txt

Một đoạn mã từ trang người dùng OSX grep:

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


5
Lệnh gọi trực tiếp như egrep không được dùng nữa. Khả năng tương tự cũng có sẵn như grep -E. Đó là ... một bóng buồn của Perl, thiếu khẳng định lookaround, hầu hết các thoát xuyệc ngược, tùy chọn, điều kiện, vv người dùng :( Power sẽ ghét nó, nhưng nó ít nhất thực hiện công việc.
Dewi Morgan

1
Cảm ơn. grep -Ethay vì grep -Plà chính xác những gì tôi cần.
asmaier 25/09/19

6

use perl;

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

Nếu bạn cần nhiều greptùy chọn hơn (tôi thấy -oít nhất bạn cũng muốn ) có nhiều cách pgreptriển khai khác nhau trôi nổi trên mạng, nhiều trong số chúng ở Perl.

Nếu "gần như Perl" là đủ tốt, PCRE giao hàng với pcregrep.


5

Có thay thế khác: pcregrep.

Pcregrep là một grep với các biểu thức chính quy tương thích với Perl. Nó có cách sử dụng giống hệt như grep -P. Vì vậy, nó sẽ tương thích với các tập lệnh của bạn.

Nó có thể được cài đặt bằng homebrew:

brew install pcre


Error: No available formula for pcregrep
Aaron Brager

GaborMarton, tôi đã chỉnh sửa câu trả lời của bạn để bao gồm nhận xét sửa chữa của @Martin và phải di chuyển định dạng xung quanh một chút để vượt qua những thay đổi tối thiểu.
Daniel Baird

3

Làm thế nào về việc sử dụng tùy chọn '-E'? Nó hoạt động tốt đối với tôi, ví dụ, nếu tôi muốn kiểm tra xem có một php_zip, php_xml, php_gd2mở rộng từ php -m tôi sử dụng:

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

1
những công việc này. Mac sử dụng FreeBSD grep và Linux sử dụng GNU grep ... để sửa chữa này làm việc trên hệ điều hành MacOS tôi sierra
jimh

2

Tương đương với câu trả lời được chấp nhận, nhưng không có yêu cầu của công tắc -P, không có trên cả hai máy tôi có sẵn.

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

2

Điều này đã làm việc cho tôi:

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

0

Một giải pháp Perl khác cho -P

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

0

sử dụng perl one-liner regex bằng cách chuyển đầu ra tìm kiếm bằng một đường ống. Tôi đã sử dụng lookbehind (lấy liên kết src trong html) và lookahead cho " và chuyển đầu ra của curl (html) cho nó.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.