2011-01-22 25 views
5

Vì vậy, tôi khá tốt với các biểu thức thông thường, nhưng tôi đang gặp một số rắc rối với chúng trên Unix. Dưới đây là hai điều tôi rất muốn biết làm thế nào để làm:grep trên unix/linux: cách thay thế hoặc chụp văn bản?

1) Thay thế tất cả văn bản ngoại trừ chữ cái, số, và nhấn

Trong PHP tôi muốn làm điều này: (các công trình lớn)

 
preg_replace('#[^a-zA-Z0-9_]#','',$text). 

Trong bash tôi đã thử điều này (với thành công hạn chế); có vẻ như nó doesnt phép bạn sử dụng toàn bộ các regex:

 
text="my #1 example!" 
${text/[^a-zA-Z0-9_]/'') 

Tôi đã thử nó với sed nhưng nó vẫn có vẻ có vấn đề với các thiết lập regex đầy đủ:

echo "my #1 example!" | sed s/[^a-zA-Z0-9\_]// 

Tôi chắc chắn có một cách để làm điều đó với grep cũng vậy, nhưng nó đã phá vỡ nó thành nhiều dòng khi tôi đã cố gắng:

echo abc\!\@\#\$\%\^\&\*\(222 | grep -Eos '[a-zA-Z0-9\_]+'

Và cuối cùng tôi cũng đã cố gắng sử dụng expr nhưng nó có vẻ như vậy có thực sự hỗ trợ hạn chế cho regex mở rộng ...


2) Capture (nhiều) các bộ phận của văn bản

Trong PHP tôi chỉ có thể làm một cái gì đó như thế này:

 
preg_match('#(word1).*(word2)#',$text,$matches); 

Tôi không chắc chắn điều đó có thể thực hiện được như thế nào trong * nix ...

+0

Xem thêm: 'perl' – derobert

Trả lời

14

Phần 1

Bạn đang ở gần đó với sed chỉ cần thêm modifier g để thay thế xảy ra trên toàn cầu, mà không có sự g, thay thế sẽ xảy ra chỉ một lần.

$ echo "my #1 example!" | sed s/[^a-zA-Z0-9\_]//g 
my1example 
$ 

Bạn đã phạm sai lầm tương tự với mô hình thay thế bash của bạn quá: không làm thay thế toàn cầu:

$ text="my #1 example!" 

# non-global replacement. Only the space is delete. 
$ echo ${text/[^a-zA-Z0-9_]/''} 
my#1 example! 

# global replacement by adding an additional/
$ echo ${text//[^a-zA-Z0-9_]/''} 
my1example 

Phần 2

chụp hoạt động tương tự trong sed như nó đã làm trong PHP regex: kèm theo mẫu trong dấu ngoặc đơn kích hoạt chụp:

# swap foo and bar's number using capturing and back reference. 
$ echo 'foo1 bar2' | sed -r 's/foo([0-9]+) bar([0-9]+)/foo\2 bar\1/' 
foo2 bar1 
$ 
1

Để thay thế cho câu trả lời hay của codaddict bằng cách sử dụng sed, bạn cũng có thể sử dụng tr cho phần đầu tiên của câu hỏi.

echo "my #1 _ example!" | tr -d -C '[[:alnum:]_]' 

Tôi cũng đã sử dụng lớp ký tự [:alnum:], chỉ để hiển thị tùy chọn khác.

+0

Lưu ý, các': vĩ mô: 'tính năng trong' tr' là không đồng nhất giữa hiện thực và có thể thiếu hoàn toàn. Ví dụ, 'tr' của busybox thiếu chúng hoàn toàn (hoặc đã làm, lần cuối tôi kiểm tra) –

0

ý của bạn là gì bạn không thể sử dụng cú pháp regex cho bash?

$ text="my #1 example!" 
$ echo ${text//[^a-zA-Z0-9_]/} 
my1example 

bạn phải sử dụng // cho hơn 1 lần thay thế.

cho câu hỏi thứ 2 của bạn, với bash 3.2 ++

$ [[ $text =~ "(my).*(example)" ]] 
$ echo ${BASH_REMATCH[1]} 
my 
$ echo ${BASH_REMATCH[2]} 
example 
Các vấn đề liên quan