sed: ¿cómo capitalizar cada tercera palabra?

9

Dado:

main_east_library
main_west_roof
main_north_roof
minor_south_roof

¿Cómo se utiliza I sed(en concreto, no awk, tr, etc.) para crear:

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)_' 

Aunque eso da:

sed: -e expression #1, char 16: Invalid back reference
Michael Durrant
fuente
1
sin awk o tr, su sed fallará si lo prueba en un sistema heredado o simplemente en otro. ¡Algunas de las expresiones en las respuestas son extensiones GNU!
ikrabbe

Respuestas:

11

Con GNU sed:

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

Capitalizaría la tercera secuencia de letras de cada línea.

Para capitalizar cada tercera secuencia de letras en cada línea:

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

Para capitalizar cada tercera secuencia de letras en toda la entrada , con GNU awk:

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

O con perl:

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

Si bien la [[:alpha:]]clase de caracteres puede ser un poco aleatoria en algunos sistemas (por ejemplo, en sistemas GNU, eso incluye muchos números con la exclusión de los árabes (0123456789)), Perl \p{...}se basa en propiedades de caracteres Unicode. Por lo tanto \p{alpha}, incluirán letras en todos los alfabetos y también caracteres alfabéticos que no sean letras.

Sin embargo, no incluirá la combinación de signos diacríticos, lo que significa que palabras como Stéphanese considerarían como dos palabras separadas.

Por lo tanto, es posible que desee en su lugar:

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

Aunque eso puede terminar incluyendo demasiados.

También tenga en cuenta que, a diferencia de GNU sed, Perl \utransformará correctamente palabras como fiddle(donde hay un carácter de ligadura) a Fiddle(2 caracteres Fy i).

Stéphane Chazelas
fuente
3

perl

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

Cuenta 2 secuencias de caracteres que terminan con guión bajo, luego pone en mayúscula el siguiente carácter.

Glenn Jackman
fuente
2

Otra GNU sed:

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

Esto supone que la línea siempre comienza con una palabra.

Cuonglm
fuente