2009-07-27 26 views
34

xem xét đầu vào:trừ dòng đầu tiên và cuối cùng từ sed/START /,/END/

=sec1= 
some-line 
some-other-line 

foo 
bar=baz 

=sec2= 
c=baz 

Nếu tôi muốn xử lý chỉ = Sec1 = Tôi có thể ví dụ như nhận xét ra phần theo:

sed -e '/=sec1=/,/=[a-z]*=/s:^:#:' < input 

... tốt, gần như.

này sẽ bình luận các dòng bao gồm "= Sec1 =" và "= sec2 =" dòng, và kết quả sẽ là một cái gì đó như:

#=sec1= 
#some-line 
#some-other-line 
# 
#foo 
#bar=baz 
# 
#=sec2= 
c=baz 

Câu hỏi của tôi là: cách dễ nhất là gì loại trừ các dòng bắt đầu và kết thúc từ một/START /,/END/range trong sed?

Tôi biết rằng đối với nhiều trường hợp, sàng lọc móng vuốt "s :::" có thể đưa ra giải pháp trong trường hợp cụ thể này, nhưng tôi là giải pháp chung ở đây.

Trong "Sed - An Introduction and Tutorial" Bruce Barnett viết: "Tôi sẽ chỉ cho bạn sau cách hạn chế lệnh lên, nhưng không bao gồm dòng chứa mẫu được chỉ định", nhưng tôi không thể tìm thấy nơi anh thực sự hiển thị .

Trong "USEFUL ONE-LINE SCRIPTS FOR SED" Biên soạn bởi Eric Pement, tôi có thể tìm thấy chỉ là ví dụ bao gồm:

# print section of file between two regular expressions (inclusive) 
sed -n '/Iowa/,/Montana/p'    # case sensitive 

Trả lời

31

này nên làm như lừa:

sed -e '/=sec1=/,/=sec2=/ { /=sec1=/b; /=sec2=/b; s/^/#/ }' < input 

này phù hợp giữa Sec1 và sec2 toàn diện và sau đó chỉ bỏ qua dòng đầu tiên và dòng cuối cùng với lệnh b. Điều này để lại các dòng mong muốn giữa sec1 và sec2 (độc quyền), và lệnh s thêm dấu chú thích.

Thật không may, bạn cần phải lặp lại các regexps để khớp các dấu phân tách. Theo như tôi biết không có cách nào tốt hơn để làm điều này. Ít nhất bạn có thể giữ cho các regexps sạch sẽ, mặc dù chúng được sử dụng hai lần.

này được chuyển thể từ SED FAQ: How do I address all the lines between RE1 and RE2, excluding the lines themselves?

+0

Vâng, đây chính xác là những gì tôi đang được tìm kiếm. Cảm ơn. –

+0

Đối với folks trên macOS với BSD sed bạn cần sử dụng các dòng mới thực sự thay vì dấu chấm phẩy. Để biết thêm chi tiết, hãy xem [answer] (http://stackoverflow.com/a/15470635/2909897) – mbigras

+1

không chắc chắn về các phiên bản khác, nhưng với GNU sed, điều này có thể dễ dàng thực hiện bằng cách sử dụng ''/ = sec1 = /,/= sec2 =/{//! s/^/# /} ''... từ [thủ công] (https://www.gnu.org/software/sed/manual/sed.html#Regexp-Addresses)' biểu thức chính quy trống' // 'lặp lại biểu thức chính quy cuối cùng khớp với ' – Sundeep

1

bạn cũng có thể sử dụng awk

awk '/sec1/{f=1;print;next}f && !/sec2/{ $0="#"$0}/sec2/{f=0}1' file 
11

Nếu bạn không quan tâm đến dòng bên ngoài của dãy núi này, nhưng chỉ muốn các biến thể không bao gồm các Iowa/Montana ví dụ từ câu hỏi (đó là những gì mang lại cho tôi ở đây), bạn có thể viết mệnh đề "ngoại trừ các dòng đầu tiên và cuối cùng phù hợp" một cách dễ dàng đủ với sed thứ hai:

sed -n '/PATTERN1/,/PATTERN2/p' < input | sed '1d;$d'

Cá nhân, tôi tìm thấy điều này hơi rõ ràng hơn (mặc dù chậm hơn trên các tập tin lớn) so với tương đương

sed -n '1,/PATTERN1/d;/PATTERN2/q;p' < input

+0

'. Ngoài ra, phiên bản thứ hai không thổi phồng php vì pesky $ đó. – orolo

+0

Tôi có linh cảm, chúng không tương đương, nếu có nhiều hơn một trong các phạm vi đó trong luồng/tệp. – Dan

5

Một cách khác sẽ

sed '/begin/,/end/ { 
     /begin/n 
     /end/ !p 
    }' 

/begin/n -> bỏ qua dòng mà có "bắt đầu" mẫu
/end/ !p -> in tất cả các dòng không có mẫu "cuối"

Taken từ hướng dẫn sed Bruce Barnett của http://www.grymoire.com/Unix/Sed.html#toc-uh-35a

0

Tôi đã sử dụng:

sed '/begin/,/end/{/begin\|end/!p}' 

này sẽ tìm kiếm tất cả các ranh giới giữa các mô hình, sau đó in tất cả mọi thứ không chứa các mô hình

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