sed - comment capitaliser tous les 3 mots?

9

Donné:

main_east_library
main_west_roof
main_north_roof
minor_south_roof

Comment puis - je utiliser sed( en particulier, non awk, tretc.) pour créer:

main_east_Library
main_west_Roof
main_north_Roof
minor_south_Roof

Quelque chose comme:

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

Bien que cela donne:

sed: -e expression #1, char 16: Invalid back reference
Michael Durrant
la source
1
sans awk ou tr, votre sed échouera si vous l'essayez sur un système hérité ou simplement sur un autre système. Certaines des expressions dans les réponses sont des extensions GNU!
ikrabbe

Réponses:

11

Avec GNU sed:

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

Serait en majuscule la troisième séquence de lettres de chaque ligne.

Pour mettre en majuscule une troisième séquence de lettres sur chaque ligne:

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

Pour mettre une troisième séquence de lettres en majuscule dans l'entrée entière , avec GNU awk:

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

Ou avec perl:

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

Alors que la [[:alpha:]]classe de caractères peut être un peu aléatoire sur certains systèmes (par exemple sur les systèmes GNU, qui comprend de nombreux chiffres à l'exclusion des arabes (0123456789)), Perl \p{...}est basé sur les propriétés des caractères Unicode. Ainsi, ceux- \p{alpha}ci incluront des lettres dans tous les alphabets et également des caractères alphabétiques non-lettres.

Cela n'inclura pas la combinaison de signes diacritiques, ce qui signifie que des mots comme Stéphaneseraient considérés comme deux mots distincts.

Vous voudrez peut-être plutôt:

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

Bien que cela puisse finir par en inclure trop.

Notez également que contrairement à GNU sed, Perl \utransformera correctement des mots comme fiddle(où est un caractère de ligature) en Fiddle(2 caractères Fet i).

Stéphane Chazelas
la source
3

perl

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

Il compte 2 séquences de caractères se terminant par un trait de soulignement, puis met en majuscule le caractère suivant.

glenn jackman
la source
2

Un autre GNU sed:

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

Cela suppose que la ligne commence toujours par un mot.

cuonglm
la source