【发布时间】:2010-12-27 06:35:21
【问题描述】:
如何使用任何在线命令(如 sed 等)将格式为 ABC_DEF_GHI 的字符串转换为 AbcDefGhi?
【问题讨论】:
标签: shell unix sed pattern-matching
如何使用任何在线命令(如 sed 等)将格式为 ABC_DEF_GHI 的字符串转换为 AbcDefGhi?
【问题讨论】:
标签: shell unix sed pattern-matching
这是使用 gawk 的单行代码:
echo ABC_DEF_GHI | gawk 'function cap(s){return toupper(substr(s,1,1))tolower(substr(s,2))}{n=split($0,x,"_");for(i=1;i<=n;i++)o=o cap(x[i]); print o}'
AbcDefGhi
【讨论】:
优化awk 1-liner
awk -v RS=_ '{printf "%s%s", substr($0,1,1), tolower(substr($0,2))}'
优化sed1-liner
sed 's/\(.\)\(..\)_\(.\)\(..\)_\(.\)\(..\)/\1\L\2\U\3\L\4\U\5\L\6/'
【讨论】:
编辑:
这是gawk 版本:
gawk -F_ '{for (i=1;i<=NF;i++) printf "%s%s",substr($i,1,1),tolower(substr($i,2)); printf "\n"}'
原文:
为此使用sed 非常可怕:
sed -r 'h;s/(^|_)./\n/g;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;x;s/((^|_)(.))[^_]*/\3\n/g;G;:a;s/(^.*)([^\n])\n\n(.*)\n([^\n]*)$/\1\n\2\4\3/;ta;s/\n//g'
这里分解:
# make a copy in hold space
h;
# replace all the characters which will remain upper case with newlines
s/(^|_)./\n/g;
# lowercase all the remaining characters
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;
# swap the copy into pattern space and the lowercase characters into hold space
x;
# discard all but the characters which will remain upper case
s/((^|_)(.))[^_]*/\3\n/g;
# append the lower case characters to the end of pattern space
G;
# top of the loop
:a;
# shuffle the lower case characters back into their proper positions (see below)
s/(^.*)([^\n])\n\n(.*)\n([^\n]*)$/\1\n\2\4\3/;
# if a replacement was made, branch to the top of the loop
ta;
# remove all the newlines
s/\n//g
以下是随机播放的工作原理:
在它开始的时候,这是模式空间的样子:
A
D
G
bc
ef
hi
随机播放循环选取最后一个换行符和结尾之间的字符串,并将其移动到两个连续换行符(实际上是三个)之前的位置,并将额外的换行符移动到它之前跟随的字符之前。
在循环的第一步之后,模式空间是这样的:
A
D
Ghi
bc
ef
并且处理过程类似地继续,直到在额外的换行符之前没有任何内容,此时匹配失败并且不采用循环分支。
如果你想给以空格分隔的单词序列命名,脚本类似:
$ echo 'BEST MOVIE THIS YEAR' | sed -r 'h;s/(^| )./\n/g;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;x;s/((^| ).)[^ ]*/\1\n/g;G;:a;s/(^.*)( [^\n]*)\n\n(.*)\n([^\n]*)$/\1\n\2\4\3/;ta;s/^([^\n]*)(.*)\n([^\n]*)$/\1\3\2/;s/\n//g'
Best Movie This Year
【讨论】:
使用 perl 的一个衬里:
$ echo 'ABC_DEF_GHI' | perl -npe 's/([A-Z])([^_]+)_?/$1\L$2\E/g;'
AbcDefGhi
【讨论】:
这可能对你有用:
echo "ABC_DEF_GHI" |
sed 'h;s/\(.\)[^_]*\(_\|$\)/\1/g;x;y/'$(printf "%s" {A..Z} / {a..z})'/;G;:a;s/\(\(^[a-z]\)\|_\([a-z]\)\)\([^\n]*\n\)\(.\)/\5\4/;ta;s/\n//'
AbcDefGhi
或使用 GNU sed:
echo "ABC_DEF_GHI" | sed 's/\([A-Z]\)\([^_]*\)\(_\|$\)/\1\L\2/g'
AbcDefGhi
【讨论】:
带 tr 的不那么可怕的 sed 版本:
回声 ABC_DEF_GHI | sed -e 's/_//g' - | tr 'A-Z' 'a-z'
【讨论】:
abcdefghi,它不与AbcDefGhi相同