Nhận xét tất cả các dòng từ dòng nhận xét cuối cùng đến dòng với 'foo'


12

Xem xét một tệp văn bản users.txt:

#alice
#bob
charlie
dotan
eric

Tôi cần bình luận mọi thứ từ (độc quyền) dòng bình luận cuối cùng cho đến khi (bao gồm) dotan. Đây là kết quả:

#alice
#bob
#charlie
#dotan
eric

Có một sedoneliner tốt đẹp để làm điều này? Tôi sẽ hài lòng với bất kỳ công cụ nào, không chỉ sed, thực sự.

Hiện tại tôi đang nhận được số dòng của dòng nhận xét cuối cùng như vậy:

$ cat -n users.txt | grep '#' | tail -n1
  2 #bob

Sau đó tôi thêm một và nhận xét với sed:

$ sed -i'' '3,/dotan/ s/^/#/' users.txt

Tôi biết rằng tôi có thể thông minh và kết hợp tất cả những thứ này với một bcchiếc áo lót xấu xí. Chắc chắn phải có cách sạch hơn?

Câu trả lời:


5

Làm thế nào về

perl -pe '$n=1 if s/^dotan/#$&/; s/^[^#]/#$&/ unless $n==1;' file

hoặc, cùng một ý tưởng trong awk:

awk '(/^dotan/){a=1; sub(/^/,"#",$1)} (a!=1 && $1!~/^#/){sub(/^/,"#",$1);}1; ' file

7

Nếu các dòng nhận xét hiện tại tạo thành một khối liền kề duy nhất, thì bạn có thể khớp với dòng nhận xét đầu tiên thay vào đó, chỉ nhận xét những dòng đó lên đến và bao gồm cả mẫu kết thúc của bạn chưa được nhận xét

sed '/^#/,/dotan/ s/^[^#]/#&/' file

Nếu các bình luận hiện tại không liền kề nhau, thì do tính chất tham lam của trận đấu phạm vi sed tôi nghĩ bạn sẽ cần phải làm một cái gì đó như

tac file | sed '/dotan/,/^#/ s/^[^#]/#&/' | tac

tức là khớp từ trên xuống từ mẫu kết thúc với nhận xét 'đầu tiên' - rõ ràng điều đó không thuận tiện nếu bạn muốn một giải pháp tại chỗ.


4

Bạn có thể xử lý cả hai trường hợp (các dòng nhận xét trong một khối liền kề hoặc xen kẽ giữa các dòng không có dấu) với một lệnh sedgọi duy nhất :

sed '1,/PATTERN/{/^#/{x;1d;b};//!{H;/PATTERN/!{1h;d};//{x;s/\n/&#/g}}}' infile

Điều này chỉ xử lý các dòng trong 1,/PATTERN/phạm vi. Nó xthay đổi giữ không gian w. không gian mẫu mỗi khi một dòng được nhận xét (vì vậy không bao giờ có nhiều hơn một dòng nhận xét trong bộ đệm giữ) và nối thêm mỗi dòng không được nhận xét vào Hkhông gian cũ (khi trên dòng thứ nhất, 1dvà tương ứng 1hcũng cần thiết để loại bỏ ban đầu dòng trống trong bộ đệm giữ).
Khi nó đạt đến dòng khớp với MẪU, nó cũng nối nó vào Hbộ đệm cũ, e xthay đổi bộ đệm và sau đó thay thế mọi \nký tự ewline trong không gian mẫu bằng một \newline và #(nghĩa là tất cả các dòng trong không gian mẫu sẽ bắt đầu bằng #, bao gồm dòng đầu tiên là dòng đầu tiên trong không gian giữ luôn là một dòng nhận xét).
Với một mẫu infile:

alice
#bob
bill
#charlie
ding
dong
dotan
jimmy
#garry

đang chạy:

sed '1,/dotan/{                   # if line is in this range    -start c1
/^#/{                             # if line is commented        -start c2
x                                 # exchage hold space w. pattern space
1d                                # if 1st line, delete pattern space
b                                 # branch to end of script
}                                 #                             -end c2
//!{                              # if line is not commented    -start c3
H                                 # append to hold space
/dotan/!{                         # if line doesn't match dotan -start c4
1h                                # if 1st line, overwrite hold space
d                                 # delete pattern space
}                                 #                             -end c4
//{                               # if line matches dotan       -start c5
x                                 # exchage hold space w. pattern space
s/\n/&#/g                         # add # after each newline character
}                                 #                             -end c5
}                                 #                             -end c3
}' infile                         #                             -end c1

đầu ra:

alice
#bob
bill
#charlie
#ding
#dong
#dotan
jimmy
#garry

vì vậy, nó chỉ nhận xét các dòng từ (và loại trừ) #charliecho đến (và bao gồm) dotanvà để các dòng khác không bị ảnh hưởng.
Chắc chắn, điều này giả định luôn có ít nhất một dòng nhận xét trước khi khớp dòng PATTERN. Nếu đó không phải là trường hợp bạn có thể thêm một kiểm tra bổ sung trước khi thay thế:/^#/{s/\n/&#/g}


Cảm ơn bạn, tôi sẽ có khá nhiều để học hỏi từ câu trả lời này!
dotancohen

Đợi đã, tôi phải làm hỏng việc. Đây không phải là về loạt bình luận cuối cùng ? Không, tôi hiểu rồi Loạt cuối cùng + dotan. Khá thông minh chết tiệt.
mikeerv

1
Bạn luôn tìm thấy những câu hỏi hay nhất. Dotan chết tiệt đã cho tôi ném một lúc - có lẽ vẫn vậy, tôi chưa thử nó. cảm ơn, không
mikeerv 13/07/2015

2

Đây là một sed:

sed  -e:n -e'/\n#.*\ndotan/!{$!{N;/^#/bn'      \
-eb  -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et  -e\} -eP\;D <in >out

Điều đó làm như bạn yêu cầu. Nó chỉ hoạt động trên một ngăn xếp - xây dựng nó khi cần thiết và miễn là cần thiết giữa các lần xuất hiện của các dòng nhận xét và bỏ bộ đệm cũ có lợi cho dòng nhận xét mới hơn nữa trong đầu vào khi tìm thấy. Hình ảnh...

nhập mô tả hình ảnh ở đây

Xin lỗi, tôi không biết tại sao tôi lại làm vậy. Nhưng nó đến với tâm trí.

Dù sao, sedtrải đều bộ đệm của nó giữa mỗi dòng nhận xét cuối cùng trong bất kỳ loạt nào, không bao giờ giữ lại một bộ đệm nào trong bộ đệm của nó hơn là cần thiết để theo dõi chính xác sự xuất hiện nhận xét cuối cùng và nếu bất cứ lúc nào nó gặp dòng cuối cùng trong khi thực hiện thì nó sẽ cố gắng gtuyên bố thực hiện thùy cuối cùng và nhánh test toàn bộ bộ đệm sẽ được in, nếu không nó sẽP trích xuất tất cả các dòng mà nó phát hành từ bộ đệm ngay khi nó được thực hiện.

Tôi đoán đây là những gì mang lại cho accordion tâm trí ...

printf %s\\n   \#alice \#bob charlie dotan eric \
               \#alice \#bob charlie dotan eric \
               \#alice \#bob charlie dotan eric |
sed  -e:n -e'l;/\n#.*\ndotan/!{$!{N;/^#/bn'     \
-eb  -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g'  \
-et  -e\} -eP\;D

#alice
#alice\n#bob$
#alice\n#bob\ncharlie$
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob
#charlie
#dotan
eric

Chỉ có một sự khác biệt giữa lệnh này và lệnh trên và đó là llệnh ook ở trên cùng. Khi chúng ta lnhìn vào sedkhông gian mô hình khi nó hoạt động, chúng ta có thể hiểu rõ hơn về những gì diễn ra sau hậu trường và hiểu rõ hơn về cách điều khiển những nỗ lực của nó.

Trong trường hợp này, chúng ta có thể xem sedđầu vào ngăn xếp cho đến khi tìm thấy lần xuất hiện thứ hai của \n#.*\ndotanđầu vào và khi nó bắt đầu in ra một dòng trước đó một dòng. Thật tuyệt. Tôi đã học được rất nhiều làm việc về điều này.


Rất tuyệt cảm ơn bạn! Đoạn cuối cùng với lời giải thích là tuyệt vời, tôi cũng sẽ dành khá nhiều thời gian để học từ bài này. Đẹp chồng!
dotancohen

1
@dotancohen - đây là một câu hỏi thực sự tốt. Có một cái nhìn vào chỉnh sửa để xem ngăn xếp .
mikeerv

2
Tôi nhận thấy trong lịch sử chỉnh sửa mục Handle many dotans. Tôi chắc chắn rằng đây là cơn ác mộng tồi tệ nhất của vợ tôi.
dotancohen

1
@dotancohen - yeah, đây là một khó khăn. Những thứ như #\ndotan\ndotanlà khó khăn cho những điều này. Tôi có nghĩa là khi tôi nói đây là một câu hỏi hay. Tôi nghĩ rằng tôi đã nhận được nó hoàn hảo, nhưng một vấn đề bạn có thể gặp phải là nếu các khối nhận xét của bạn được phân tách bằng 1000 dòng - điều đó sẽ làm chậm nó. Bạn có thể dính một cái gì đó giống như s/\n/&/150;ttrước khi /\n#điều đầu tiên phá vỡ bộ đệm nếu nó kéo dài 150 dòng chẳng hạn. Và dù sao, có lẽ đó chỉ là những gì cô ấy đang chờ đợi tất cả cùng !
mikeerv 13/07/2015
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.