awk或sed仅小写/大写字符串中的一个字符?


13

有没有办法如何在一个字符串中仅大写/小写一个字符?

输入示例:

syslog_apr_24_30
syslog_mar_01_17

所需的输出:

syslog_Apr_24_30
syslog_Mar_01_17

请注意本月初的大写字母。

我已经尝试过,awk但是我还不足以使其正常运行。

Answers:


18

您可以\u在GNU sed中使用大写字母:

sed -e 's/_\(.\)/_\u\1/' input

Perl的作用相同:

perl -pe 's/_(.)/_\u$1/' input

\l 相反。


8
简单一点:sed 's/_./\U&/'
glenn jackman

4

awk:

echo "syslog_apr_24_30" | 
  awk -F'_' '{print $1"_"toupper(substr($2,1,1)) substr($2,2)  "_"$3"_"$4}'

3

Awk 带有子字符串和toupper的版本

awk 'BEGIN{ FS=OFS="_"} {
        cap=toupper(substr($2,1,1));
        lower=substr($2,2,3);
        $2 = cap lower; print 
}' list.txt 

样品运行:

$ awk 'BEGIN{ FS=OFS="_"} { 
    cap=toupper(substr($2,1,1));
    lower=substr($2,2,3);$2 = cap lower; print 
}' list.txt               
syslog_Apr_24_30
syslog_Mar_01_17

3

使用awk

awk -F_ '{
    printf "%s_%s_%s_%s",$1,toupper(substr($2,1,1))substr($2,2,2),$3,$4"\n"
}' foo

要么

awk -F_ '{
    for(i=1;i<=NF;i++) {
        if(i==2){
            printf "%s",toupper(substr($i,1,1))substr($i,2,length($i)-1)
        } 
        else {printf "%s",$i} 
        if(i<NF) {printf "%s","_"}
    } printf "%s","\n"}' foo

% cat foo
syslog_apr_24_30
syslog_mar_01_17

% awk -F_ '{for(i=1;i<=NF;i++) {if(i==2){printf "%s",toupper(substr($i,1,1))substr($i,2,length($i)-1)} else {printf "%s",$i} if(i<NF) {printf "%s","_"}} printf "%s","\n"}' foo
syslog_Apr_24_30
syslog_Mar_01_17

% awk -F_ '{printf "%s_%s_%s_%s",$1,toupper(substr($2,1,1))substr($2,2,2),$3,$4"\n"}' foo 
syslog_Apr_24_30
syslog_Mar_01_17

3

这是一种Perl方法:

$ perl -pe 's/_./uc($&)/e' file
syslog_Apr_24_30
syslog_Mar_01_17

-p使每一行施加由给出的脚本之后打印-e。替换用替换第一个实例_及其后的字符($&匹配的对象)为大写字母(uc()),需要e替换运算符(s///e)的末尾以求表达式的值。


2

另一个perl

perl -F_ -anle '$F[1] = ucfirst $F[1];print join "_", @F'

1

Pure Bash 4.x,使用正则表达式选择要大写的部分,以及该^^部分的大写运算符。前后粘贴(与。*匹配)以重新创建整个字符串:

foo=syslog_apr_24_30
if [[ $foo =~ (.*)(_[a-z])(.*) ]]; then
    foo=${BASH_REMATCH[1]}${BASH_REMATCH[2]^^}${BASH_REMATCH[3]}
fi

如果您不记得所有的引用规则,则可以安全地引用除正则表达式以外的所有内容(这将使=~文字字符串匹配)。

所述^upcase-第一操作员仅工作在一个变量(或数组元素)的开始。而且似乎没有任何子字符串扩展可以为您提供perl所谓的左值(您可以分配/修改)。大写/小写优先的运算符可以采用按字符匹配的模式,但这无助于跳过syslog_,因为在“ syslog”中有以字母开头的月份名称。

无论如何,这可能比foo="$(echo "$foo" | sed 's/_./\U&/')"(格伦·杰克曼(Glenn Jackman)发表的对已接受答案的评论)要快。

Bash,sed或awk比perl快许多倍。如果您开始发现在shell脚本中有用的多个perl单行代码,则应该将整个内容写在perl中。


0

如果月份始终跟在第一个“ _”(下划线)之后,则使用此字符(如其他答案所示):

sed -e 's/_\(.\)/_\u\1/'

如果在一个月前的下划线之前还有其他下划线,则以上内容将无效。

如果月份始终以第8个字符开头,请使用以下命令:

sed -e 's/^\(.\{7\}\)\(.\)/\1\u\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.