2013-07-07 30 views
72

Tôi muốn lấy hai số cuối cùng (một int, một phao; tiếp theo là khoảng trắng tùy chọn) và chỉ in chúng.sed: chỉ in nhóm phù hợp

Ví dụ:

foo bar <foo> bla 1 2 3.4 

nên in:

2 3.4 

Cho đến nay, tôi đã điều sau đây:

sed -n 's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/replacement/p' 

sẽ cho tôi

foo bar <foo> bla 1 replacement 

Tuy nhiên, nếu tôi cố gắng thay thế bằng nhóm 1, toàn bộ dòng được in.

sed -n 's/\([0-9][0-9]*[\ \t][0-9.]*[\ \t]*$\)/\1/p' 

Tôi chỉ có thể in phần của dòng khớp với regex trong nhóm?

Trả lời

80

Đối sánh toàn bộ dòng, vì vậy hãy thêm .* vào đầu regex của bạn. Điều này làm cho toàn bộ dòng để được thay thế bằng nội dung của nhóm

echo "foo bar <foo> bla 1 2 3.4" | 
sed -n 's/.*\([0-9][0-9]*[\ \t][0-9.]*[ \t]*$\)/\1/p' 
2 3.4 
+24

Tôi phải thêm tùy chọn '-r' hoặc' --regexp-extended' nếu không tôi đã nhận được 'tham chiếu không hợp lệ \ 1 trên' s 'command's RHS 'error. –

+9

@DanielSokolowski Tôi nghĩ bạn nhận được lỗi đó nếu bạn sử dụng '(' và ')' thay vì '\ (' và '\)'. –

+1

Cũng nhớ thêm '.* 'đến cuối regexp nếu chuỗi bạn muốn trích xuất không phải lúc nào cũng ở cuối dòng. –

45

grep là công cụ thích hợp cho chiết xuất.

sử dụng ví dụ của bạn và regex của bạn:

kent$ echo 'foo bar <foo> bla 1 2 3.4'|grep -o '[0-9][0-9]*[\ \t][0-9.]*[\ \t]*$' 
2 3.4 
+0

@jozxyqk điểm của bạn là? – Kent

+6

tuyệt vời cho toàn bộ nhóm, mặc dù [sed là cần thiết cho các nhóm riêng lẻ] (http://superuser.com/questions/11130/can-gnu-grep-output-a-selected-group) – jozxyqk

+0

grep -o không cổng trên các hệ thống chạy msysgit nhưng sed thì có. – cchamberlain

7

Và đối với chưa lựa chọn khác, tôi muốn đi với awk!

echo "foo bar <foo> bla 1 2 3.4" | awk '{ print $(NF-1), $NF; }' 

này sẽ chia đầu vào (Tôi đang sử dụng STDIN ở đây, nhưng đầu vào của bạn có thể dễ dàng trở thành một tập tin) trên không gian, và sau đó in ra-nhưng-người cuối cùng lĩnh vực, và sau đó là trường cuối cùng. Biến số $NF giữ số lượng trường được tìm thấy sau khi phát nổ trên dấu cách.

Lợi ích của việc này là không quan trọng nếu điều gì đứng trước hai trường cuối cùng thay đổi, miễn là bạn chỉ muốn hai trường cuối cùng sẽ tiếp tục hoạt động.

0

Lệnh cắt được thiết kế cho tình huống chính xác này. Nó sẽ "cắt" trên bất kỳ dấu phân cách nào và sau đó bạn có thể xác định khối nào sẽ được xuất.

Ví dụ: echo "foo bar <foo> bla 1 2 3.4" | cut -d " " -f 6-7

sẽ dẫn đến sản lượng: 2 3.4

-d đặt delimiter

-f chọn phạm vi 'lĩnh vực' đến đầu ra, trong trường hợp này đó là các đoạn từ 6 đến 7 của chuỗi gốc.

Các vấn đề liên quan