How may I concisely assign different values to a variable, depending on another variable?

Use a case statement (portable, works in any sh-like shell):

case "$CODE" in
    [aA] ) PN="com.tencent.ig" ;;
    [bB] ) PN="com.vng.pubgmobile" ;;
    [cC] ) PN="com.pubg.krmobile" ;;
    [dD] ) PN="com.rekoo.pubgm" ;;
    * ) printf '\a\t%s\n' 'ERROR!' 'CODE KOSONG' 'MELAKUKAN EXIT OTOMATIS' >&2
        exit 1 ;;
esac

I'd also recommend changing your variable names from all capital letters (like CODE) to something lower- or mixed-case (like code or Code). There are many all-caps names that have special meanings, and re-using one of them by accident can cause trouble.

Other notes: The standard convention is to send error messages to "standard error" rather than "standard output"; the >&2 redirect does this. Also, if a script (or program) fails, it's best to exit with a nonzero status (exit 1), so any calling context can tell what went wrong. It's also possible to use different statuses to indicate different problems (see the "EXIT CODES" section of the curl man page for a good example). (Credit to Stéphane Chazelas and Monty Harder for suggestions here.)

I recommend printf instead of echo -e (and echo -n), because it's more portable between OSes, versions, settings, etc. I once had a bunch of my scripts break because an OS update included a version of bash compiled with different options, which changed how echo behaved.

The double-quotes around $CODE aren't really needed here. The string in a case is one of the few contexts where it's safe to leave them off. However, I prefer to double-quote variable references unless there's a specific reason not to, because it's hard to keep track of where it's safe and where it isn't, so it's safer to just habitually double-quote them.


Assuming you are using bash release 4.0 or newer...

CODE=A

declare -A domain

domain=(
   [a]=com.tencent.ig
   [b]=com.vng.pubgmobile
   [c]=com.pubg.krmobile
   [d]=com.rekoo.pubgm
)

PN=${domain[${CODE,,}]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}

In the code, I define an associative array containing all the domain names, each associated with a single letter lower-case key.

The $PN variable is assigned the domain name corresponding to the lower-cased $CODE value (${CODE,,} returns the value of $CODE turned into lower case letters only) from this array, but if the $CODE does not correspond to a valid entry in the domain list, it exits the script with an error.

The ${variable:?error message} parameter substitution would expand to the value of $variable (the appropriate domain in the code) but would exit the script with the error message if the value is empty not available. You don't get exactly the same formatting of the error message as in your code, but it would essentially behave the same if $CODE is invalid:

$ bash script.sh
script.sh: line 12: domain[${CODE,,}]: ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS

If you care about character count, we can shorten this further:

CODE=A
declare -A domain=( [a]=tencent.ig [b]=vng.pubgmobile [c]=pubg.krmobile [d]=rekoo.pubgm )
PN=com.${domain[${CODE,,}]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}

Apart from deleting unnecessary newlines, I've also removed com. from each domain (this is instead added in the assignment to PN).

Note that all code above would work even for a multi-character value in $CODE (if lower-cased keys existed for these in the domain array).


If $CODE was a numerical (zero-based) index instead, this would simplify the code a bit:

CODE=0

domain=( com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm )
PN=${domain[CODE]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}

This would additionally make it really easy to read the domain array from an auxiliary file containing one entry per line:

CODE=0

readarray -t domain <domains.txt
PN=${domain[CODE]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}

If your shell allow arrays, the shortest answer should be like this example in bash:

declare -A site
site=( [a]=com.tencent.ig [b]=com.vng.pubgmobile [c]=com.pubg.krmobile [d]=com.rekoo.pubgm )

pn=${site[${code,}]}

That is assuming that $code could only be a, b, c or d.
If not, add a test like:

case ${site,} in
    a|b|c|d)        pn=${site[${code,}]};;
    *)              pn="default site"
                    printf '\a\t %s\n' 'ERROR!' 'CODE KOSONG' 'MELAKUKAN EXIT OTOMATIS'
                    exit 1
                    ;;
esac

Tags:

Shell Script