如何缩短这个 shell 脚本?
CODE="A"
if test "$CODE" = "A"
then
PN="com.tencent.ig"
elif test "$CODE" = "a"
then
PN="com.tencent.ig"
elif test "$CODE" = "B"
then
PN="com.vng.pubgmobile"
elif test "$CODE" = "b"
then
PN="com.vng.pubgmobile"
elif test "$CODE" = "C"
then
PN="com.pubg.krmobile"
elif test "$CODE" = "c"
then
PN="com.pubg.krmobile"
elif test "$CODE" = "D"
then
PN="com.rekoo.pubgm"
elif test "$CODE" = "d"
then
PN="com.rekoo.pubgm"
else
echo -e "\a\t ERROR!"
echo -e "\a\t CODE KOSONG"
echo -e "\a\t MELAKUKAN EXIT OTOMATIS"
exit
fi
答案1
使用case
语句(可移植,适用于任何sh
类似的 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
我还建议将变量名称从全部大写字母(例如CODE
)更改为小写或混合大小写(例如code
或Code
)。有许多全大写名称具有特殊含义,不小心重复使用其中之一可能会引起麻烦。
其他说明: 标准约定是将错误消息发送到“标准错误”而不是“标准输出”;重定向>&2
就是这样做的。另外,如果脚本(或程序)失败,最好以非零状态 ( exit 1
) 退出,这样任何调用上下文都可以知道出了什么问题。还可以使用不同的状态来指示不同的问题(请参阅手册curl
页一个很好的例子)。 (此处感谢 Stéphane Chazelas 和 Monty Harder 的建议。)
我建议printf
不要使用echo -e
( 和echo -n
),因为它在操作系统、版本、设置等之间更具可移植性。我曾经有过一堆脚本被破坏的情况,因为操作系统更新包含使用不同选项编译的 bash 版本,这改变了echo
行为方式。
$CODE
这里实际上并不需要双引号。 a 中的字符串case
是少数可以安全地保留它们的上下文之一。但是,我更喜欢对变量引用加双引号,除非有特定原因不这样做,因为很难跟踪哪里安全,哪里不安全,所以习惯性地用双引号引用它们会更安全。
答案2
假设您使用的是bash
4.0 或更高版本...
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}
在代码中,我定义了一个包含所有域名的关联数组,每个域名都与一个单字母小写键关联。
该$PN
变量被分配与该数组中的小写值对应的域名$CODE
(仅返回转换为小写字母的${CODE,,}
值),但如果该值不对应于列表中的有效条目,则会退出脚本并显示错误。$CODE
$CODE
domain
参数${variable:?error message}
替换将扩展到(代码中适当的域)的值,$variable
但如果该值为空且不可用,则会退出脚本并显示错误消息。您不会得到与代码中完全相同的错误消息格式,但它本质上是表现$CODE
如果无效则相同:
$ bash script.sh
script.sh: line 12: domain[${CODE,,}]: ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS
如果您关心字符数,我们可以进一步缩短:
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}
除了删除不必要的换行符之外,我还com.
从每个域中删除了它(而是将其添加到 的分配中PN
)。
请注意,上面的所有代码甚至对于多字符值也适用$CODE
(如果数组中存在这些小写键domain
)。
如果$CODE
是数字(从零开始)索引,这会稍微简化代码:
CODE=0
domain=( com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm )
PN=${domain[CODE]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}
domain
这还使得从每行包含一个条目的辅助文件中读取数组变得非常容易:
CODE=0
readarray -t domain <domains.txt
PN=${domain[CODE]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}
答案3
如果你的 shell 允许数组,最短的答案应该像 bash 中的这个例子:
declare -A site
site=( [a]=com.tencent.ig [b]=com.vng.pubgmobile [c]=com.pubg.krmobile [d]=com.rekoo.pubgm )
pn=${site[${code,}]}
这是假设$code
只能是 a、b、c 或 d。
如果没有,请添加一个测试,例如:
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
答案4
您使用字母来索引值,如果您使用数字,则变得简单如下:
code=1
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
eval pn\=\${"$code"}
这是可移植的 shell 代码,适用于大多数 shell。
对于 bash,您可以使用:pn=${!code}
,或者对于 bash/ksh/zsh 使用:pn=${@:code:1}
。
字母
如果您必须使用字母(从 a 到 z,或 A 到 Z),则必须将它们转换为索引:
code=a # or A, B, C, ... etc.
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
eval pn\=\"\${$(( ($(printf '%d' "'$code")|32)-96 ))}\"
在更长的代码中阐明每个部分的意图和含义:
code=A
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
asciival=$(( $(printf '%d' "'$code") )) # byte value of the ASCII letter.
upperval=$(( asciival | 32 )) # shift to uppercase.
indexval=$(( upperval - 96 )) # convert to an index from a=1.
eval arg\=\"\$\{$indexval\}\" # the argument at such index.
如果需要转换为小写值,请使用:($(( asciival & ~32 ))
确保未设置 ascii 值的第 6 位)。
错误代码
您的脚本在出现错误时打印的输出相当长(而且很具体)。
处理它最通用的方法是定义一个函数:
errorcode(){ exitcode=$1; shift; printf '\a\t %s\n' "$@"; exit "$exitcode"; }
然后使用您需要的特定消息调用该函数。
errorcode 27 "ERROR!" "CODE KOSONG" "MELAKUKAN EXIT OTOMATIS"
请注意,最终的退出值由下式给出exitcode
(此处的示例为 27)。
完整的脚本(带有错误检查)将变为:
errorcode(){ exitcode=$1; shift; printf '\a\t %s\n' "$@"; exit "$exitcode"; }
code=${1:-A}
case "$code" in
[a-d]|[A-D]) : ;;
*) errorcode 27 "ERROR!" "CODE KOSONG" "MELAKUKAN EXIT OTOMATIS" ;;
esac
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
eval pn\=\"\${$(( ($(printf '%d' "'$code") & ~32) - 64 ))}\"
printf 'Code=%s Argument=%s\n' "$code" "$pn"