sed - как использовать каждое 3-е слово?

9

Данный:

main_east_library
main_west_roof
main_north_roof
minor_south_roof

Как я могу использовать sed(в частности, нет awk, trи т. Д.) Для создания:

main_east_Library
main_west_Roof
main_north_Roof
minor_south_Roof

Что-то вроде:

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

Хотя это дает:

sed: -e expression #1, char 16: Invalid back reference
Майкл Даррант
источник
1
без awk или tr ваш sed потерпит неудачу, если вы попробуете его на устаревшей или просто другой системе. Некоторые выражения в ответах являются расширениями GNU!
Икраббе

Ответы:

11

С GNU sed:

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

С заглавной буквы третьей последовательности букв из каждой строки.

Прописать каждую третью последовательность букв в каждой строке:

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

Чтобы использовать каждую третью последовательность букв во всем вводе с помощью GNU awk:

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

Или с perl:

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

В то время как [[:alpha:]]класс символов может быть немного случайным в некоторых системах (например, в системах GNU, который включает в себя множество цифр, за исключением арабских (0123456789)), Perl \p{...}основан на свойствах символов Unicode. Таким образом, они \p{alpha}будут включать буквы во всех алфавитах, а также не буквенные алфавитные символы.

Это не будет включать в себя объединение диакритических знаков, хотя это означает, что такие слова как Stéphaneбудут рассматриваться как два отдельных слова.

Так что вы можете вместо этого:

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

Хотя это может в конечном итоге в том числе слишком много.

Также обратите внимание, что в отличие от GNU sed, Perl \uбудет правильно преобразовывать слова вроде fiddle(где один символ лигатуры) в Fiddle(2 символа Fи i).

Стефан Шазелас
источник
3

Perl

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

Он считает 2 последовательности символов, заканчивающиеся подчеркиванием, а затем прописными буквами следующий символ.

Гленн Джекман
источник
2

Другой GNU sed:

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

Это предполагает, что строка всегда начинается со слова.

cuonglm
источник