Shell 脚本技巧

字符串比较的最优形式 — 冗余常量(x) + “SHELL变量”

Shell 脚本的比较判读语句,一种是使用 test 命令,一种是使用中括号形式 [ ],脚本根据比较的结果进行后续动作。其中,一个比较常见、也容易出错的场景是,一个变量值与常量进行比较,如

if test $SHELL_VAR = yes; 
或
if [ $SHELL_VAR = yes ]

使用如上的原生态比较方法,由于 SHELL_VAR 取值的多样化,一些特定的变量取值会造成脚本错误或后续执行逻辑的偏离。规避这一问题的最佳方法是,使用 “冗余常量与双引号 SHELL 变量联合字符串” 的方法,即使用 x"$SHELL_VAR" 的形式代替原来的 $SHELL_VAR 形式。

错误使用1:不使用双引号 “”,不使用前缀 x

有变量 SHELL_VAR 未定义($SHELL_VAR为空)

if test $SHELL_VAR = yes; then 
--> 
if test = yes; then

显然是有语法错误,test 丢失参数。

错误使用2:不使用双引号 “”,仅仅使用前缀 x

$SHELL_VAR 值为空

if test x$SHELL_VAR = yes; then 
--> 
if test x = yes; then

看似看着是没有问题的。但是假如此时 $SHELL_VAR 值为” yes”,即 yes 前面有一个空格,则

if test x$SHELL_VAR = yes; then 
--> 
if test x yes = yes; then

显然,这样也是有语法错误的,test有两个参数 x 和 1(yes=yes)。

错误使用3:仅仅使用双引号 “”,不使用前缀 x

$SHELL_VAR 值为空

if test "$SHELL_VAR" = "yes"; then 
--> 
if test "" = "yes"; then

$SHELL_VAR 值为 ” yes”

if test "$SHELL_VAR" = "yes"; then 
--> 
if test " yes" = "yes"; then

貌似使用 “” 把变量包起来就没有问题了。但是假如此时$SHELL_VAR值为“-n”或者 “-f”

if test "$SHELL_VAR" = "yes"; then 
--> 
if test "-f" = "yes"; then

则此时 "-f" 是有二义性的,是作为 test 命令的 option 还是 test 的 argument ?

正确使用:使用双引号 “”,使用前缀 x

$SHELL_VAR 值为空

if test x"$SHELL_VAR" = x"yes"; then 
--> 
if test x"" = x"yes"; then

$SHELL_VAR 值为 ” yes”

if test x"$SHELL_VAR" = x"yes"; then 
--> 
if test x" yes" = x"yes"; then

$SHELL_VAR 值为 “-n” 或者 “-f”

if test x"$SHELL_VAR" = x"yes"; then 
--> 
if test x"-f" = x"yes"; then

在 Linux 的系统脚本中,可以常见这种用法。

这类问题,尤其是比较中的变量调用的是脚本输入参数时,如 $1$2,如果使用错误的比较形式,某种程度上也可视为针对 Shell 脚本的一种注入攻击。

Reference

  1. https://stackoverflow.com/questions/174119/why-do-shell-script-comparisons-often-use-xvar-xyes
  2. https://blog.csdn.net/JCRunner/article/details/51565212

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注