2012-09-24 29 views
7

Tôi là người mới bắt đầu đến sed. Tôi biết rằng nó có thể áp dụng một lệnh (hoặc một tập các lệnh) vào một phạm vi nhất định của dòng như vậysed - tham gia một loạt các dòng được chọn

sed '/[begin]/,/[end]/ [some command]' 

nơi [begin] là một biểu thức chính quy mà chỉ định dòng đầu của dãy núi này và [end] là một thường xuyên biểu thức chỉ định dòng kết thúc của phạm vi (nhưng được bao gồm trong phạm vi).

Tôi đang cố gắng sử dụng điều này để chỉ định một loạt các dòng trong một tệp và kết hợp tất cả các dòng đó thành một dòng. Đây là thử nghiệm tốt nhất của tôi, không hoạt động:

sed '/[begin]/,/[end]/ { 
N 
s/\n// 
} 
' 

Tôi có thể chọn tập hợp các dòng tôi muốn mà không gặp bất kỳ sự cố nào, nhưng tôi dường như không thể hợp nhất tất cả các dòng thành một dòng. Nếu bất cứ ai có thể chỉ cho tôi đi đúng hướng, tôi sẽ thực sự biết ơn.

Trả lời

5

Một cách sử dụng GNU sed:

sed -n '/begin/,/end/ { H;g; s/^\n//; /end/s/\n/ /gp }' file.txt 
+1

Cảm ơn bạn rất nhiều. Tôi không bao giờ nghĩ đến việc sử dụng không gian giữ; Tôi đã học được rất nhiều từ câu trả lời của bạn. – Setris

+0

Lưu ý rằng thao tác này sẽ hủy * tất cả các dòng khác *. Xem bên dưới câu trả lời của @Thor để có giải pháp mạnh mẽ hơn. – krlmlr

1

Tôi thích câu hỏi của bạn. Tôi cũng thích Sed. Đáng tiếc, tôi không biết làm thế nào để trả lời câu hỏi của bạn trong Sed; vì vậy, giống như bạn, tôi đang xem ở đây cho câu trả lời.

Vì không có câu trả lời Sed vẫn chưa xuất hiện ở đây, ở đây là làm thế nào để làm điều đó trong Perl:

perl -wne 'my $flag = 0; while (<>) { chomp; if (/[begin]/) {$flag = 1;} print if $flag; if (/[end]/) {print "\n" if $flag; $flag = 0;} } print "\n" if $flag;' 
+0

Cảm ơn bạn đã thực hiện trong Perl. Tôi đã có ý nghĩa để tìm hiểu nó trong một thời gian, vì vậy tôi sẽ thêm nó vào bộ sưu tập của tôi về đoạn mã để nghiên cứu. – Setris

2

Đây là thẳng về phía trước nếu bạn muốn chọn một số dòng và tham gia cùng họ. Sử dụng câu trả lời Steve's hoặc giải pháp thay thế đường ống của tôi:

sed -n '/begin/,/end/p' | tr -d '\n' 

Sẽ trở nên phức tạp hơn nếu bạn muốn giữ các dòng khác. Dưới đây là cách tôi sẽ làm điều đó (với GNU sed):

join.sed

/\[begin\]/ { 
    :a 
    /\[end\]/! { N; ba } 
    s/\n/ /g 
} 

Vì vậy, logic ở đây là:

  1. Khi [begin] dòng được gặp bắt đầu thu thập dòng vào không gian mô hình với một vòng lặp.
  2. Khi [end] được tìm thấy, hãy ngừng thu thập và tham gia các tuyến.

Ví dụ:

seq 9 | sed -e '3s/^/[begin]\n/' -e '6s/$/\n[end]/' | sed -f join.sed 

Output:

1 
2 
[begin] 3 4 5 6 [end] 
7 
8 
9 
+0

tại sao không sed -n '/ begin /,/end/p' | gzip | gunzip | tr -d '\ n' trong khi ở đó? – Valer

+0

@Valer: Tôi không chắc tôi hiểu điểm của bạn. Tuy nhiên, tôi đã thêm một ví dụ thứ hai có thể tham gia các dòng được chọn trong khi vẫn giữ phần còn lại của tệp. – Thor

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