Komentari semua baris dari baris komentar terakhir hingga baris dengan 'foo'

12

Pertimbangkan file teks users.txt:

#alice
#bob
charlie
dotan
eric

Saya perlu mengomentari semuanya dari (eksklusif) baris komentar terakhir hingga (inklusif) dotan. Ini hasilnya:

#alice
#bob
#charlie
#dotan
eric

Apakah ada sedoneliner yang bagus untuk melakukan ini? Saya akan senang dengan alat apa pun, bukan hanya sed, sungguh.

Saat ini saya mendapatkan nomor baris dari komentar terakhir sebagai:

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

Saya kemudian menambahkan satu dan berkomentar dengan sed:

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

Saya tahu bahwa saya bisa menjadi pandai dan menggabungkan semua ini dengan beberapa bcyang jelek. Tentunya harus ada cara yang lebih bersih?

dotancohen
sumber

Jawaban:

5

Bagaimana tentang

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

atau, ide yang sama dalam awk:

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

Jika baris komentar yang ada membentuk satu blok bersebelahan, maka Anda bisa mencocokkan dari baris komentar pertama , mengomentari hanya garis-garis tersebut hingga dan termasuk pola akhir Anda yang belum dikomentari

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

Jika komentar yang ada tidak berdekatan, maka karena sifat serakah dari pertandingan sed range saya pikir Anda perlu melakukan sesuatu seperti

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

yaitu mencocokkan ke atas dari pola akhir ke komentar 'pertama' - jelas itu tidak begitu nyaman jika Anda menginginkan solusi di tempat.

Steeldriver
sumber
4

Anda dapat menangani kedua kasus (baris komentar dalam satu blok yang berdekatan atau diselingi di antara baris yang tidak dikomandoi) dengan satu sedpermintaan:

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

Ini hanya memproses garis dalam 1,/PATTERN/rentang. Itu xperubahan terus ruang w. ruang pola setiap kali sebuah baris dikomentari (jadi tidak pernah ada lebih dari satu baris yang dikomentari dalam ruang tunggu) dan menambahkan setiap baris yang tidak dikomentari ke Hruang lama (ketika pada baris pertama, 1ddan masing 1h- masing juga diperlukan untuk menghapus inisial baris kosong di buffer penahan).
Ketika mencapai POLA pencocokan garis, itu juga menambahkannya ke Hbuffer lama, e xmengubah buffer dan kemudian mengganti setiap \nkarakter ewline dalam ruang pola dengan \newline dan #(yaitu, semua garis dalam ruang pola sekarang akan dimulai dengan #, termasuk baris pertama sebagai baris pertama di ruang tunggu selalu merupakan baris yang dikomentari).
Dengan sampel infile:

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

berlari:

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

output:

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

jadi itu hanya mengomentari baris dari (dan tidak termasuk) #charliehingga (dan termasuk) dotandan membiarkan baris lain tidak tersentuh.
Tentu, ini mengasumsikan selalu ada setidaknya satu baris komentar sebelum pencocokan baris PATTERN. Jika bukan itu masalahnya, Anda dapat menambahkan cek tambahan sebelum penggantian:/^#/{s/\n/&#/g}

don_crissti
sumber
Terima kasih, saya akan belajar sedikit dari jawaban ini!
dotancohen
Tunggu dulu, aku pasti mengacau. Ini bukan tentang rangkaian komentar terakhir ? Tidak, saya mengerti. Seri terakhir + dotan. Cukup pintar.
mikeserv
1
Anda selalu menemukan pertanyaan terbaik. Dotan sialan membuatku terlempar sebentar - mungkin masih, aku belum mencobanya. terima kasih, don.
mikeserv
2

Ini yang lain sed:

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

Itu sesuai dengan yang Anda minta. Ini hanya bekerja pada tumpukan - membangunnya bila perlu dan selama diperlukan antara kemunculan baris yang dikomentari, dan membuang buffer lama demi baris komentar baru lebih lanjut di input ketika menemukan satu. Gambar...

masukkan deskripsi gambar di sini

Maaf, saya tidak tahu mengapa saya melakukan itu. Tapi itu terlintas dalam pikiran.

Bagaimanapun, sedsebarkan buffernya di antara setiap baris komentar terakhir dalam seri apa pun, jangan pernah menyimpan satu pun buffer lebih dari yang diperlukan untuk secara akurat melacak kejadian yang terakhir dikomentari, dan jika sewaktu-waktu ia menemukan baris terakhir saat melakukan itu akan mencoba gpernyataan eksekusi lobal terakhir dan cabang tseluruh buffer keluar untuk dicetak, kalau tidak itu akan Pmembatalkan semua baris yang dilepaskan dari buffer segera setelah itu.

Saya kira inilah yang membawa akordeon ke pikiran ...

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

Hanya ada satu perbedaan antara perintah ini dan yang di atas dan itu adalah lperintah ook di atas. Ketika kita lmelihat sedruang pola saat berfungsi, kita bisa mendapatkan ide yang lebih baik tentang apa yang terjadi di balik layar dan pemahaman yang lebih baik tentang bagaimana mengarahkan usahanya.

Dalam hal ini kita dapat menonton sedinput tumpukan hingga menemukan kemunculan \n#.*\ndotaninput kedua, dan ketika itu mulai mencetak baris sebelumnya pada satu waktu. Agak keren. Saya belajar banyak tentang ini.

mikeserv
sumber
Sangat baik terima kasih! Paragraf terakhir dengan penjelasannya luar biasa, saya akan meluangkan cukup banyak waktu untuk belajar dari pos ini juga. Tumpukan bagus!
dotancohen
1
@dotancohen - ini pertanyaan yang sangat bagus. Lihatlah hasil edit untuk melihat tumpukan .
mikeserv
2
Saya perhatikan dalam riwayat edit entri Handle many dotans. Saya yakin ini adalah mimpi terburuk istri saya.
dotancohen
1
@dotancohen - ya, ini yang sulit. Hal-hal seperti #\ndotan\ndotansulit untuk hal-hal ini. Maksud saya ketika saya mengatakan ini pertanyaan yang bagus. Saya pikir saya mendapatkannya dengan sempurna, tetapi satu masalah yang bisa Anda temui adalah jika blok komentar Anda dipisahkan oleh 1000 baris - yang akan memperlambatnya. Anda mungkin menempel sesuatu seperti s/\n/&/150;tsebelum /\n#hal pertama untuk keluar buffer jika itu mencakup 150 baris, misalnya. Dan lagi pula, mungkin itu hanya apa yang dia telah menunggu sepanjang !
mikeserv