【问题标题】:assign number value to alphabet in shell/bash在 shell/bash 中为字母分配数字值
【发布时间】:2014-12-15 17:01:00
【问题描述】:

我有一个脚本,提示用户输入 3 个字母的代码。对于该代码的前两个字母,我需要将该代码转换为与 a=01b=02....等对应的数字。
例如,用户输入 ABC for $SITECODE 我需要将 A&B 转换为 0102 并将其存储到新变量中。

#!/bin/bash


# enable logging
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>/var/log/ULFirstBoot.log 2>&1

###################################### global variables ######################################################

# top level domain
tld="somedomain.com"

# grabs the serial number for ComputerName
serial=`/usr/sbin/system_profiler SPHardwareDataType | /usr/bin/awk '/Serial\ Number\ \(system\)/ {print $NF}'`

# Cocoadialog location
CD="/Users/Shared/cocoaDialog.app/Contents/MacOS/cocoaDialog"


################################################### Begin Define Functions ####################################################

userinput () # Function will promt for Username,SItecode, and Region using Cocoadialog
{
    # Prompt for username
rv=($($CD inputbox --title "User Name" --no-newline --informative-text "Please Enter the Users Employee ID" --icon "user" --button1 "NEXT" --button2 "Cancel"))

USERNAME=${rv[1]}

if [ "$rv" == "1" ]; then
    echo "`date` User clicked Next"
    echo "`date` Username set to ${USERNAME}"
    elif [ "$rv" == "2" ]; then
    echo "`date` User Canceled"
    exit
fi

# Dialog to enter the User name and the create $SITECODE variable
rv=($($CD inputbox --title "SiteCode" --no-newline --informative-text "Enter Site Code" --icon "globe" --button1 "NEXT" --button2 "Cancel"))

SITECODE=${rv[1]} #truncate leading 1 from username input 


if [ "$rv" == "1" ]; then
    echo "`date` User clicked Next"
    echo "`date` Sitecode set to ${SITECODE}"
    elif [ "$rv" == "2" ]; then
    echo "`date` User Canceled"
    exit
fi

# Dialog to enter the Password and the create $REGION variable
rv=($($CD dropdown --title "REGION" --text "Choose Region" --no-newline --icon "globe" --items NA EULA AP --button1 "OK" --button2 "Cancel"))

item=${rv[1]}


if [[ "$rv" == "1" ]] 
    then echo "`date` User clicked OK"
    elif [[ "$rv" == "2" ]] 
        then echo "`date` User Canceled"
        exit
fi

if [ "$item" == "0" ]; then
    REGION="NA"
    echo "`date` Region set to NA"
    elif [ "$item" == "1" ]; then
    REGION="EULA"
    echo "`date` Region set to EULA"
    elif [ "$item" == "2" ]; then
    REGION="AP"
    echo "`date` Region Set to AP"
fi


# Confirm that settings are correct

rv=($($CD msgbox --text "Verify settings are correct" --no-newline --informative-text "USER-$USERNAME REGION-$REGION, SITE CODE-$SITECODE" --button1 "Yes" --button2 "Cancel"))

if [[ "$rv" == "1" ]]
    then echo "`date` User clicked OK"
    elif [[ "$rv" == "2" ]] 
        then echo "`date` User Canceled"
        exit
fi


}

# Sets computername based
setname ()
{
    ComputerName=$SITECODE$serial

    /usr/sbin/scutil --set ComputerName $SITECODE$serial  
    echo "`date` Computer Name Set to" $(/usr/sbin/scutil --get ComputerName)
    /usr/sbin/scutil --set LocalHostName $SITECODE$serial
    echo  "`date` LocalHostname set to" $(/usr/sbin/scutil --get LocalHostName)
    /usr/sbin/scutil --set HostName $SITECODE$serial.$tld
    echo "`date` Hostname set to" $(/usr/sbin/scutil --get HostName)

}

adbind () 
{
    OU="ou=Computers,ou=${SITECODE}Win7,ou=$REGION,dc=global,dc=ul,dc=com"
    echo "`date` OU will be set to $OU"
    dsconfigad -add "global.ul.com" -username "user" -password "password" -ou "$OU" 
    dsconfigad -mobile "enable" -mobileconfirm "disable" -groups "Domain Admins, ADMIN.UL.LAPTOPADMINS"
}

# Checks if machine is succesfully bound to AD before proceeding
adcheck () 
{
    until [ "${check4AD}" = "Active Directory" ]; do
    check4AD=`/usr/bin/dscl localhost -list . | grep "Active Directory"`
    sleep 5s 
    done
}

adduser () # creates mobile user account based on userinput function
{
    # create mobile user account and home directory at /Users/username
    /System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount -n $USERNAME -h /Users/$USERNAME 
    # Add newly created user to local admins group
    dscl . -append /Groups/admin GroupMembership $USERNAME
    # set login window to show username and password promts not a list of users
    defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 1
}

setADMPass ()
{
        parsed1=${SITECODE:0:1}
parsed2=${SITECODE:1:1}
}

####################################### End define Functions ####################################################


############################################# Bgin Main Script #######################################################

userinput
setname
adbind
adcheck
adduser
echo $(dscl . -read /Groups/admin GroupMembership)
echo $(defaults 'read' /Library/Preferences/com.apple.loginwindow.plist SHOWFULLNAME)
# Reboot to apply changes
shutdown -r now "Rebooting to enable Mobile accounts"

【问题讨论】:

  • 错了什么?显示一些示例输入、所需的输出以及您到目前为止所写的内容
  • 您在写这方面有什么困难?到目前为止你写了什么?
  • 你在乎,上 ABC 与下 abc 大小写吗?
  • 根据case 问题,进行一次(或两次)查找(例如alower=abcdefghijklmnopqrstuvwxyz,然后循环输入并获取所需字母的索引(例如$(expr index $alower $yourchar)
  • 我有代码来解析字符串中的字母 parsed1=${SITECODE:0:1} parsed2=${SITECODE:1:1}

标签: bash shell


【解决方案1】:

这是一种有趣的编码方式,滥用 Bash 的算法:

string2code() {
    # $1 is string to be converted
    # return variable is string2code_ret
    # $1 should consist of alphabetic ascii characters, otherwise return 1
    # Each character is converted to its position in alphabet:
    # a=01, b=02, ..., z=26
    # case is ignored
    local string=$1
    [[ $string = +([[:ascii:]]) ]] || return 1
    [[ $string = +([[:alpha:]]) ]] || return 1
    string2code_ret=
    while [[ $string ]]; do
        printf -v string2code_ret '%s%02d' "$string2code_ret" "$((36#${string::1}-9))"
        string=${string:1}
    done
}

试试看:

$ string2code abc; echo "$string2code_ret"
010203
$ string2code ABC; echo "$string2code_ret"
010203

魔法发生在这里:

$((36#${string::1}-9))

36# 一词告诉 Bash,以下数字以基数 36 表示。在这种情况下,Bash 会考虑字符 01、...、9abc、...、z(忽略大小写)。术语${string:1} 扩展为string 的第一个字符。

【讨论】:

  • 更智能的解决方案; +1 =)
  • :) 好一个。不过有一点,他只要求输入前 2 个字符。
  • @ArunSangal 然后很容易:只将字符串的前两个字符传递给函数(例如,使用${var::2})或修改函数string2code,使其仅在前两个字符。这个练习留给读者!但感谢您指出这一点,我在 OP 中完全错过了它。
【解决方案2】:

我找到了答案,感谢您的帮助!

setADMPass ()
    {
        alower=abcdefghijklmnopqrstuvwxyz

        site=$(echo $SITECODE | tr '[:upper:]' '[:lower:]')
        parsed1=${site:0:1}
        parsed2=${site:1:1}

        tmp1=${alower%%$parsed1*}     # Remove the search string and everything after it
        ch1=$(( ${#tmp1} + 1 ))

        tmp2=${alower%%$parsed2*}     # Remove the search string and everything after it
        ch2=$(( ${#tmp2} + 1 ))

        if [[ $ch1 -lt 10 ]]; then
            #statements
            ch1=0$ch1
        fi

        if [[ $ch2 -lt 10 ]]; then
            #statements
            ch2=0$ch2
        fi

        passpre=$ch1$ch2


    }

【讨论】:

    【解决方案3】:

    看看这是否有帮助!重击 4+。如果您发现任何问题,那将是您的功课。

    #!/bin/bash
    
    declare -A koba
    i=1
    
    for vi in {a..z};do koba=(["$vi"]="0${i}"); ((i++)); done
    for vi in {A..Z};do koba=(["$vi"]="0${i}"); ((i++)); done
    
    echo -en "\nEnter a word: "; read w; w="$( echo $w | sed "s/\(.\)/\1 /g" | cut -d' ' -f1,2)";
    
    new_var="$(for ch in $w; do echo -n "${koba["${ch}"]}"; done)";
    
    echo $new_var;
    

    【讨论】:

      猜你喜欢
      • 2019-03-25
      • 2017-05-31
      • 2022-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-19
      • 1970-01-01
      • 2018-05-01
      相关资源
      最近更新 更多