sed - wie kann man jedes dritte Wort groß schreiben?

9

Gegeben:

main_east_library
main_west_roof
main_north_roof
minor_south_roof

Wie kann ich verwendet sed(genauer gesagt, nicht awk, tretc.) zu erstellen:

main_east_Library
main_west_Roof
main_north_Roof
minor_south_Roof

Etwas wie:

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

Obwohl das gibt:

sed: -e expression #1, char 16: Invalid back reference
Michael Durrant
quelle
1
ohne awk oder tr schlägt Ihr sed fehl, wenn Sie es auf einem Legacy- oder einem anderen System ausprobieren. Einige der Ausdrücke in den Antworten sind GNU-Erweiterungen!
Ikrabbe

Antworten:

11

Mit GNU sed:

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

Würde die dritte Folge von Buchstaben aus jeder Zeile groß schreiben.

So schreiben Sie jede dritte Buchstabenfolge in jeder Zeile groß :

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

So schreiben Sie mit GNU jede dritte Buchstabenfolge in der gesamten Eingabe groß awk:

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

Oder mit perl:

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

Während die [[:alpha:]]Zeichenklasse auf einigen Systemen etwas zufällig sein kann (z. B. auf GNU-Systemen, die viele Ziffern enthalten, mit Ausnahme der arabischen (0123456789)), \p{...}basiert Perl auf Unicode-Zeicheneigenschaften. Diese \p{alpha}enthalten also Buchstaben in allen Alphabeten sowie alphabetische Zeichen ohne Buchstaben.

Es wird jedoch keine Kombination von Diakritika enthalten, was bedeutet, dass Wörter wie Stéphaneals zwei separate Wörter betrachtet werden.

Vielleicht möchten Sie stattdessen:

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

Dies kann jedoch zu vielen führen.

Beachten Sie auch, dass sedPerl im Gegensatz zu GNU \uWörter wie fiddle(wobei ein Ligaturzeichen ist) korrekt in Fiddle(2 Zeichen Fund i) umwandelt .

Stéphane Chazelas
quelle
3

Perl

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

Es werden 2 Zeichenfolgen gezählt, die mit einem Unterstrich enden, und dann das nächste Zeichen in Großbuchstaben geschrieben.

Glenn Jackman
quelle
2

Ein weiteres GNU sed:

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

Dies setzt voraus, dass die Zeile immer mit einem Wort beginnt.

cuonglm
quelle