nhóm bắt sed không hoạt động


27

Tôi có một chuỗi các định dạng [0-9]+\.[0-9]+\.[0-9]. Tôi cần trích xuất các số thứ nhất, thứ hai và thứ ba một cách riêng biệt. Theo tôi hiểu, các nhóm bắt giữ nên có khả năng này. Tôi có thể sử dụng sed "s/\([0-9]*\)/\1/gđể có được số thứ nhất, sed "s/\([0-9]*\)/\2/gđể có được số thứ hai và sed "s/\([0-9]*\)/\3/gđể có được số thứ ba. Trong mỗi trường hợp, mặc dù, tôi nhận được toàn bộ chuỗi. Tại sao chuyện này đang xảy ra?


6
Các nhóm bắt giữ toàn bộ nhóm ... không phải các thành phần riêng lẻ trong nhóm. Bạn cần một cái gì đó như 's/\([0-9]\)\([0-9]\)\([0-9]\).*/\1\2\3/'để nắm bắt số lượng cá nhân.
Munir

Câu trả lời:


45

Chúng tôi không thể cung cấp cho bạn câu trả lời đầy đủ mà không có ví dụ về đầu vào của bạn nhưng tôi có thể nói với bạn rằng sự hiểu biết của bạn về các nhóm chụp là sai. Bạn không sử dụng chúng tuần tự, chúng chỉ đề cập đến biểu thức chính ở phía bên trái của cùng một toán tử thay thế. Nếu bạn chụp, ví dụ /(foo)(bar)(baz)/, sau đó foosẽ \1, barsẽ \2bazsẽ \3. Bạn không thể làm s/(foo)/\1/; s/(bar)/\2/, bởi vì, trong s///cuộc gọi thứ hai , chỉ có một nhóm bị bắt, do đó \2sẽ không được xác định.

Vì vậy, để nắm bắt ba nhóm chữ số của bạn, bạn sẽ cần phải làm:

sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1 : \2 : \3/'

Hoặc, càng dễ đọc hơn:

sed -E 's/([0-9]*)\.([0-9]*)\.([0-9]*)/\1 : \2 : \3/'

1
Lợi ích của việc thoát khỏi dấu ngoặc trong ví dụ đầu tiên là gì?
Josh M.

2
@JoshM. bạn cần phải thoát chúng để chúng được sử dụng để chụp các mẫu. Thông thường /(foo)/trong sed sẽ phù hợp với một (nhân vật theo nghĩa đen , tiếp theo foovà sau đó là một nghĩa đen ). Nếu bạn muốn chụp một nhóm, bạn cần thoát dấu ngoặc đơn hoặc sử dụng -Etùy chọn.
terdon

Tôi hầu như luôn sử dụng -rcờ vì vậy tôi cho rằng đó là lý do tại sao tôi chưa gặp phải vấn đề này.
Josh M.

1
@JoshM. vâng, -rcờ cũng sẽ làm điều đó, nhưng nó không phải là di động. GNU sed hỗ trợ nó nhưng nhiều người khác thì không. Là -Ephổ quát hơn.
terdon

9

Thí dụ:

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'
123

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'
456

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'
78

Hoặc, tất cả cùng nhau:

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1 : \2 : \3/'
123 : 456 : 78

2

Sử dụng Sed với -r, - được mở rộng để tránh tất cả dấu ngoặc đơn thoát.

echo "1234.567.89" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1, \2, \3/' 
1234, 567, 89    #output
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.