sed-如何将每个第三个单词大写?


9

鉴于:

main_east_library
main_west_roof
main_north_roof
minor_south_roof

我怎样才能使用sed(特别是,不awktr等等)来创建:

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扩展!
ikrabbe

Answers:


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个字符Fi)。


3

佩尔

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

它计算2个以下划线结尾的字符序列,然后将下一个字符大写。


2

另一个GNU sed

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

假设行始终以单词开头。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.