【问题标题】:sed help - convert a string of form ABC_DEF_GHI to AbcDefGhised help - 将 ABC_DEF_GHI 形式的字符串转换为 AbcDefGhi
【发布时间】:2010-12-27 06:35:21
【问题描述】:

如何使用任何在线命令(如 sed 等)将格式为 ABC_DEF_GHI 的字符串转换为 AbcDefGhi?

【问题讨论】:

    标签: shell unix sed pattern-matching


    【解决方案1】:

    这是使用 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

    【讨论】:

      【解决方案2】:

      优化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/'
      

      【讨论】:

        【解决方案3】:

        编辑:

        这是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
        

        【讨论】:

          【解决方案4】:

          使用 perl 的一个衬里:

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

          【讨论】:

            【解决方案5】:

            这可能对你有用:

            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
            

            【讨论】:

              【解决方案6】:

              带 tr 的不那么可怕的 sed 版本:

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

              【讨论】:

              • 脚本的输出是abcdefghi,它不与AbcDefGhi相同
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-11-15
              • 1970-01-01
              • 2011-05-29
              • 2020-10-04
              相关资源
              最近更新 更多