How do you echo a 4-digit Unicode character in Bash?

后端 未结 18 1800
醉梦人生
醉梦人生 2020-11-29 14:38

I\'d like to add the Unicode skull and crossbones to my shell prompt (specifically the \'SKULL AND CROSSBONES\' (U+2620)), but I can\'t figure out the magic incantation to m

相关标签:
18条回答
  • 2020-11-29 15:06

    You may need to encode the code point as octal in order for prompt expansion to correctly decode it.

    U+2620 encoded as UTF-8 is E2 98 A0.

    So in Bash,

    export PS1="\342\230\240"
    

    will make your shell prompt into skull and bones.

    0 讨论(0)
  • 2020-11-29 15:07
    % echo -e '\u2620'     # \u takes four hexadecimal digits
    ☠
    % echo -e '\U0001f602' # \U takes eight hexadecimal digits
                                                                        
    0 讨论(0)
  • 2020-11-29 15:09

    Here's a fully internal Bash implementation, no forking, unlimited size of Unicode characters.

    fast_chr() {
        local __octal
        local __char
        printf -v __octal '%03o' $1
        printf -v __char \\$__octal
        REPLY=$__char
    }
    
    function unichr {
        local c=$1    # Ordinal of char
        local l=0    # Byte ctr
        local o=63    # Ceiling
        local p=128    # Accum. bits
        local s=''    # Output string
    
        (( c < 0x80 )) && { fast_chr "$c"; echo -n "$REPLY"; return; }
    
        while (( c > o )); do
            fast_chr $(( t = 0x80 | c & 0x3f ))
            s="$REPLY$s"
            (( c >>= 6, l++, p += o+1, o>>=1 ))
        done
    
        fast_chr $(( t = p | c ))
        echo -n "$REPLY$s"
    }
    
    ## test harness
    for (( i=0x2500; i<0x2600; i++ )); do
        unichr $i
    done
    

    Output was:

    ─━│┃┄┅┆┇┈┉┊┋┌┍┎┏
    ┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
    ┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯
    ┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
    ╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏
    ═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
    ╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯
    ╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
    ▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏
    ▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
    ■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯
    ▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
    ◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●
    ◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
    ◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯
    ◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
    
    0 讨论(0)
  • 2020-11-29 15:11

    Quick one-liner to convert UTF-8 characters into their 3-byte format:

    var="$(echo -n '☠' | od -An -tx1)"; printf '\\x%s' ${var^^}; echo
    
    0 讨论(0)
  • 2020-11-29 15:12

    In Bash:

    UnicodePointToUtf8()
    {
        local x="$1"               # ok if '0x2620'
        x=${x/\\u/0x}              # '\u2620' -> '0x2620'
        x=${x/U+/0x}; x=${x/u+/0x} # 'U-2620' -> '0x2620'
        x=$((x)) # from hex to decimal
        local y=$x n=0
        [ $x -ge 0 ] || return 1
        while [ $y -gt 0 ]; do y=$((y>>1)); n=$((n+1)); done
        if [ $n -le 7 ]; then       # 7
            y=$x
        elif [ $n -le 11 ]; then    # 5+6
            y=" $(( ((x>> 6)&0x1F)+0xC0 )) \
                $(( (x&0x3F)+0x80 ))" 
        elif [ $n -le 16 ]; then    # 4+6+6
            y=" $(( ((x>>12)&0x0F)+0xE0 )) \
                $(( ((x>> 6)&0x3F)+0x80 )) \
                $(( (x&0x3F)+0x80 ))"
        else                        # 3+6+6+6
            y=" $(( ((x>>18)&0x07)+0xF0 )) \
                $(( ((x>>12)&0x3F)+0x80 )) \
                $(( ((x>> 6)&0x3F)+0x80 )) \
                $(( (x&0x3F)+0x80 ))"
        fi
        printf -v y '\\x%x' $y
        echo -n -e $y
    }
    
    # test
    for (( i=0x2500; i<0x2600; i++ )); do
        UnicodePointToUtf8 $i
        [ "$(( i+1 & 0x1f ))" != 0 ] || echo ""
    done
    x='U+2620'
    echo "$x -> $(UnicodePointToUtf8 $x)"
    
    

    Output:

    ─━│┃┄┅┆┇┈┉┊┋┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟
    ┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻┼┽┾┿
    ╀╁╂╃╄╅╆╇╈╉╊╋╌╍╎╏═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟
    ╠╡╢╣╤╥╦╧╨╩╪╫╬╭╮╯╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿
    ▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟
    ■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿
    ◀◁◂◃◄◅◆◇◈◉◊○◌◍◎●◐◑◒◓◔◕◖◗◘◙◚◛◜◝◞◟
    ◠◡◢◣◤◥◦◧◨◩◪◫◬◭◮◯◰◱◲◳◴◵◶◷◸◹◺◻◼◽◾◿
    U+2620 -> ☠
    
    0 讨论(0)
  • 2020-11-29 15:12

    If hex value of unicode character is known

    H="2620"
    printf "%b" "\u$H"
    

    If the decimal value of a unicode character is known

    declare -i U=2*4096+6*256+2*16
    printf -vH "%x" $U              # convert to hex
    printf "%b" "\u$H"
    
    0 讨论(0)
提交回复
热议问题