sed - como capitalizar cada terceira palavra?

9

Dado:

main_east_library
main_west_roof
main_north_roof
minor_south_roof

Como posso usado sed(especificamente, não awk, tr, etc.) para criar:

main_east_Library
main_west_Roof
main_north_Roof
minor_south_Roof

Algo como:

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

Embora isso dê:

sed: -e expression #1, char 16: Invalid back reference
Michael Durrant
fonte
1
sem awk ou tr, seu sed falhará se você tentar em um legado ou apenas em outro sistema. Algumas das expressões nas respostas são extensões GNU!
ikrabbe

Respostas:

11

Com o GNU sed:

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

Colocaria em maiúscula a terceira sequência de letras de cada linha.

Para colocar em maiúscula cada terceira sequência de letras em cada linha:

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

Para capitalizar cada terceira sequência de letras em toda a entrada , com o GNU awk:

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

Ou com perl:

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

Embora a [[:alpha:]]classe de caracteres possa ser um pouco aleatória em alguns sistemas (por exemplo, em sistemas GNU, que inclui muitos números com exclusão dos números árabes (0123456789)), o Perl \p{...}é baseado nas propriedades de caracteres Unicode. Portanto, eles \p{alpha}incluirão letras em todos os alfabetos e também caracteres alfabéticos que não sejam letras.

Não incluirá a combinação de diacríticos, o que significa que palavras como Stéphaneseriam consideradas duas palavras separadas.

Então você pode querer:

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

Embora isso possa acabar incluindo muitos.

Observe também que, ao contrário do GNU sed, o Perl's \utransformará corretamente palavras como fiddle(onde há um caractere de ligadura) em Fiddle(2 caracteres Fe i).

Stéphane Chazelas
fonte
3

perl

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

Ele conta 2 sequências de caracteres que terminam com sublinhado e, em maiúsculas, o próximo caractere.

Glenn Jackman
fonte
2

Outro GNU sed:

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

Isso pressupõe que a linha sempre comece com uma palavra.

cuonglm
fonte