sed - bagaimana cara memanfaatkan setiap kata ke 3?

9

Diberikan:

main_east_library
main_west_roof
main_north_roof
minor_south_roof

Bagaimana saya bisa digunakan sed(khusus, tidak awk, tr, dll) untuk membuat:

main_east_Library
main_west_Roof
main_north_Roof
minor_south_Roof

Sesuatu seperti:

$ echo "main_west_library
main_west_roof
main_north_roof
minor_south_roof" | sed 's_\3_upcase(\3)_' 

Meskipun itu memberi:

sed: -e expression #1, char 16: Invalid back reference
Michael Durrant
sumber
1
tanpa awk atau tr sed Anda akan gagal jika Anda mencobanya pada warisan atau hanya sistem lainnya. Beberapa ekspresi dalam jawabannya adalah ekstensi GNU!
ikrabbe

Jawaban:

11

Dengan GNU sed:

sed -E 's/[[:alpha:]]+/\u&/3'

Akan menggunakan huruf kapital urutan ketiga dari setiap baris.

Untuk mengkapitalisasi setiap urutan ketiga huruf di setiap baris:

sed -E 's/(([[:alpha:]]+[^[:alpha:]]+){2})([[:alpha:]]+)/\1\u\3/g'

Untuk mengkapitalisasi setiap urutan ketiga huruf dalam seluruh input , dengan GNU awk:

awk -v RS='[^[:alpha:]]+' -v ORS= '
   NR % 3 == 0 {$0=toupper(substr($0,1,1)) substr($0,2)}
   {print $0 RT}'

Atau dengan perl:

perl -Mopen=locale -pe 's/\p{alpha}+/++$n % 3 == 0 ? "\u$&" : "$&"/ge'

Sementara [[:alpha:]]kelas karakter dapat sedikit acak pada beberapa sistem (misalnya pada sistem GNU, yang mencakup banyak angka dengan mengesampingkan yang berbahasa Arab (0123456789)), Perl's \p{...}didasarkan pada properti karakter Unicode. Jadi itu \p{alpha}akan termasuk huruf dalam semua huruf dan juga karakter alfabet non-huruf.

Itu tidak akan termasuk menggabungkan diakritik meskipun yang berarti bahwa kata-kata seperti Stéphaneakan dianggap sebagai dua kata yang terpisah.

Jadi, Anda mungkin ingin sebagai gantinya:

perl -Mopen=locale -pe 's/[\p{alpha}\p{mark}]+/++$n % 3 == 0 ? "\u$&" : "$&"/ge'

Padahal itu mungkin saja termasuk terlalu banyak.

Juga perhatikan bahwa bertentangan dengan GNU sed, Perl \uakan benar mengubah kata-kata seperti fiddle(di mana satu karakter pengikat) ke Fiddle(2 karakter Fdan i).

Stéphane Chazelas
sumber
3

perl

perl -pe 's/(?:.*?_){2}\K./\u$&/'

Itu menghitung 2 urutan karakter yang berakhir dengan garis bawah, lalu huruf besar karakter berikutnya.

glenn jackman
sumber
2

GNU lain sed:

sed -E 's/([^[:alpha:]])([[:alpha:]])/\1\u\2/2'

Ini mengasumsikan bahwa baris selalu dimulai dengan sebuah kata.

cuonglm
sumber