2013-05-20 45 views
7

Hãy giúp tôi sử dụng sed. Tôi có một tệp như dưới đây.Sed để trích xuất văn bản giữa hai chuỗi

START=A 
    xxxxx 
    xxxxx 
END 
START=A 
    xxxxx 
    xxxxx 
END 
START=A 
    xxxxx 
    xxxxx 
END 
START=B 
    xxxxx 
    xxxxx 
END 
START=A 
    xxxxx 
    xxxxx 
END 
START=C 
    xxxxx 
    xxxxx 
END 
START=A 
    xxxxx 
    xxxxx 
END 
START=D 
    xxxxx 
    xxxxx 
END 

Tôi muốn nhận văn bản giữa START = A, END. Tôi đã sử dụng truy vấn dưới đây.

sed '/^START=A/,/^END/!d' input_file 

Vấn đề ở đây là, Tôi nhận

START=A 
    xxxxx 
    xxxxx 
END 
START=D 
    xxxxx 
    xxxxx 
END 

thay vì

START=A 
    xxxxx 
    xxxxx 
END 

Sed thấy tham lam.

Hãy giúp tôi giải quyết vấn đề này.

Xin cảm ơn trước.

Tôi có thể sử dụng AWK để đạt được mục tiêu trên không?

Trả lời

19
sed -n '/^START=A$/,/^END$/p' data 

Tùy chọn -n có nghĩa là không in theo mặc định; sau đó kịch bản nói 'làm in giữa dòng có chứa START=AEND tiếp theo.

Bạn cũng có thể làm điều đó với awk:

Một mô hình có thể bao gồm hai mô hình phân cách bằng dấu phẩy; trong trường hợp này, hành động được thực hiện cho tất cả các dòng từ sự xuất hiện của mẫu đầu tiên mặc dù xảy ra lần thứ hai.

(từ man awk trên Mac OS X).

awk '/^START=A$/,/^END$/ { print }' data 

Cho một hình thức sửa đổi của tập tin dữ liệu trong câu hỏi:

START=A 
    xxx01 
    xxx02 
END 
START=A 
    xxx03 
    xxx04 
END 
START=A 
    xxx05 
    xxx06 
END 
START=B 
    xxx07 
    xxx08 
END 
START=A 
    xxx09 
    xxx10 
END 
START=C 
    xxx11 
    xxx12 
END 
START=A 
    xxx13 
    xxx14 
END 
START=D 
    xxx15 
    xxx16 
END 

Sản lượng sử dụng GNU sed hoặc Mac OS X (BSD) sed, và sử dụng GNU awk hoặc BSD awk, là giống:

START=A 
    xxx01 
    xxx02 
END 
START=A 
    xxx03 
    xxx04 
END 
START=A 
    xxx05 
    xxx06 
END 
START=A 
    xxx09 
    xxx10 
END 
START=A 
    xxx13 
    xxx14 
END 

Lưu ý cách tôi sửa đổi tệp dữ liệu để dễ dàng thấy nơi các khối dữ liệu khác nhau được in ca tôi từ trong tập tin.

Nếu bạn có yêu cầu đầu ra khác (chẳng hạn như 'chỉ khối đầu tiên giữa START = A và END', hoặc 'chỉ là cuối cùng ...'), thì bạn cần nêu rõ hơn trong câu hỏi.

+1

Cảm ơn bạn đã trả lời. Tôi cần văn bản giữa START = A và END tiếp theo, phần trên cung cấp dữ liệu giữa START = A và END cuối cùng. Hy vọng bạn có prob của tôi. – ranganath111

+0

Không, không. Cả hai kịch bản 'awk' và' sed' - ít nhất là trên máy tính của tôi với bản sao của tệp dữ liệu bạn đã cung cấp - in 5 khối dữ liệu giữa 'START = A' và' END', và các khối với 'START = B' đến 'END',' START = C' thành 'END' và' START = D' thành 'END' đều bị bỏ qua từ đầu ra. Bạn đang thử nghiệm nền tảng nào? Bạn đang sử dụng phiên bản 'sed' nào? Bạn đang sử dụng phiên bản 'awk' nào? (Tôi lưu ý rằng dữ liệu thử nghiệm của bạn lặp lại nguyên văn các khối giữa 'START = A' và' END'. Sẽ tốt hơn nếu bạn có các dòng khác nhau ở giữa để bạn có thể xem dòng nào đang được in.) –

+0

Khi tôi kiểm tra điều này , bắt đầu và kết thúc toeks được bao gồm trong đầu ra, trong khi tôi đã có ấn tượng OP chỉ muốn dữ liệu GIỮA chúng. –

2

Biểu thức sed của bạn có khoảng trắng trước khi kết thúc, tức là / ^END/. Vì vậy, sed lấy mẫu bắt đầu, nhưng không có mẫu kết thúc và tiếp tục in cho đến khi kết thúc. Sử dụng sed '/^START=A/, /^END/!d' input_file (thông báo /^END/)

+0

Điểm tốt về không gian trong regex 'sed', mặc dù nó làm cho sản lượng được trích dẫn thậm chí còn khó hiểu hơn (như trong 'Tôi không thể tái tạo trích dẫn đầu ra với kịch bản gốc, nhưng thả không gian không liên quan và nó hoạt động tốt, mặc dù cackhanded '). Bạn ít nhất có thể đơn giản hóa phần cuối của tập lệnh 'awk' thành'/END/{flag = 0} 'có thể đặt cờ thành 0 khi nó đã bằng 0, nhưng điều đó không gây hại. Bạn cũng có thể sử dụng '/ START = A /,/END/{print}' đơn giản hơn nhiều. –

+0

yea, '/ START = A /,/END/{print}' điều này đơn giản hơn nhiều, nhưng nó đã được hiển thị trong câu trả lời của bạn :) Tôi chỉ đang chơi với một lá cờ :). Trên thực tế, sau giải pháp 'awk' bạn đã đưa ra, anh ta không cần phải làm gì khác. Tôi sẽ loại bỏ giải pháp 'awk' của tôi. Nó có thể dẫn đến sự nhầm lẫn nhiều hơn làm bất kỳ tốt: P – abasu

+0

có .. Tôi đã có nó .. Cảm ơn rất nhiều – ranganath111

3

Phiên bản cơ bản ...

sed -n '/START=A/,/END/p' yourfile 

phiên bản mạnh mẽ hơn ...

sed -n '/^ *START=A *$/,/^ *END *$/p' yourfile 
+0

bạn có thể giải thích những gì ',' có nghĩa là trong chuỗi mẫu sed? –

+0

@Vikrant - ',' tách hai phần của một phạm vi * được xác định bởi hai regex để các đường thẳng giữa mẫu đầu tiên và mẫu thứ hai được trả về. – starfry

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