开发者

sed help - convert a string of form ABC_DEF_GHI to AbcDefGhi

开发者 https://www.devze.com 2023-02-01 12:24 出处:网络
How can covert a stri开发者_运维知识库ng of form ABC_DEF_GHI to AbcDefGhi using any online command such as sed etc. ?Here\'s a one-liner using gawk:

How can covert a stri开发者_运维知识库ng of form ABC_DEF_GHI to AbcDefGhi using any online command such as sed etc. ?


Here's a one-liner using 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


Optimized awk 1-liner

awk -v RS=_ '{printf "%s%s", substr($0,1,1), tolower(substr($0,2))}'

Optimized sed 1-liner

sed 's/\(.\)\(..\)_\(.\)\(..\)_\(.\)\(..\)/\1\L\2\U\3\L\4\U\5\L\6/'


Edit:

Here's a gawk version:

gawk -F_ '{for (i=1;i<=NF;i++) printf "%s%s",substr($i,1,1),tolower(substr($i,2)); printf "\n"}'

Original:

Using sed for this is pretty scary:

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'

Here it is broken down:

# 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

Here's how the shuffle works:

At the time it starts, this is what pattern space looks like:

A
D
G

bc
ef
hi

The shuffle loop picks up the string that's between the last newline and the end and moves it to the position before the two consecutive newlines (actually three) and moves the extra newline so it's before the character that it previously followed.

After the first step through the loop, this is what pattern space looks like:

A
D

Ghi
bc
ef

And processing proceeds similarly until there's nothing before the extra newline at which point the match fails and the loop branch is not taken.

If you want to title case a sequence of words separated by spaces, the script would be similar:

$ 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


One liner using perl:

$ echo 'ABC_DEF_GHI' | perl -npe 's/([A-Z])([^_]+)_?/$1\L$2\E/g;'
AbcDefGhi


This might work for you:

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

Or using GNU sed:

echo "ABC_DEF_GHI" | sed 's/\([A-Z]\)\([^_]*\)\(_\|$\)/\1\L\2/g'
AbcDefGhi


Less scary sed version with tr:

echo ABC_DEF_GHI | sed -e 's/_//g' - | tr 'A-Z' 'a-z'

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号