我试图在Bash中使用[[]]操作符并且严重失败。我的脚本是:
#!/bin/bash
# Test driver for the ProtectDatae script
set -o xtrace
# [[ -z "$1" ]] || source="$1" && source=""
if [[ -z "%1" ]]
then
source=""
else
source=$1
fi
[[ -z "$2" ]] || target="$2" && target="" # This does not work
[[ -z "$3" ]] || sourceBackup="$3" && sourceBackup="/tmp/sourcebackup" # This does not work
source cmd.sh # Get a function to run a Linux command
if [[ -e "$sourceBackup" && "$sourceBackup" -ne "" ]]
then
# If a source backup directory is specified then get rid of any old directory and make a new backup
# and verify it. If OK, make the source directory be the source backup directory
# otherwise work directly in the source directory
if [[ -e "$sourceBackup" ]]
then
cmd "sudo rm -R $sourceBackup" "empty backup directory $sourceBackup failed"
cmd "cp -apu $source $sourceBackup" "backup home directory"
cmd "diff -aprN ~/$source/* $sourceBackup" "bad backup in $sourceBackup"
source="$sourceBackup"
fi
fi
exit 0
命令调用是./TestProtectData.sh "~" /tmp/jfghome /tmp/jfgbackup
+ source='~'
+ [[ -z /tmp/jfghome ]]
+ target=/tmp/jfghome
+ target=""
+ [[ -z /tmp/jfgbackup ]]
+ sourceBackup=/tmp/jfgbackup
+ sourceBackup=/tmp/sourcebackup
+ source cmd.sh
+ [[ -e /tmp/sourcebackup ]]
+ exit 0
下面一行发生的是错误。两个替代方案似乎都被执行了,变量最终设置不正确:
[[ -z "$2" ]] || target="$2" && target=""
我试了两个订单&&和||它们都给出了相同的结果,变量target
被设置为空白。在下一行中,将变量sourceBackup
设置为第二个备选项时会发生类似的事情,并且两个备选项似乎都被执行。如果我使用if then
结构,它可以工作。我做错了什么?
我做错了什么?
您的预期逻辑与您正在使用的bash结构不匹配。这条线:
[[ -z "$2" ]] || target="$2" && target="" # This does not work
分解为平均if 2 is not empty set target to $2. If that command succeeds, set target to ""
。&&
左边的命令总是会成功——-z
测试成功或者target="$2"
测试成功。因此,target=""
总是在最后运行。
您可以使用if ... ; then ...; else ...; fi
或查看以下方法在bash中实现三元操作符,包括:
#!/bin/bash -e
[[ -z "$3" ]] && sourceBackup="/tmp/sourcebackup" || sourceBackup="$3"
echo $sourceBackup
% ./t.sh 1 2 3
3
这里,如果-z
测试成功,我们将sourceBackup
设置为默认值。如果测试失败,$3
不为空,我们将sourceBackup
设置为$3
。
重申一下,这是而不是与三级操作符完全相同。但是如果你的顺序是正确的,它就会起作用。
普通赋值(foo=bar
)总是将状态码设置为0,因此在target
被设置为$2
之后,它立即被设置为空。我将从把逻辑颠倒过来开始:
target= # Set to empty string
[[ -z $2 ]] && target=$2
然而,这是多余的。你可以直接写
target=$2
不做任何[[...]]
-test。如果第二个参数为空,则target
也将为空。如果不为空,target
将获取该值。
有一点需要考虑:如果您决定打开set -u
,以捕获未初始化的变量,如果没有第二个参数,target=$2
将中止脚本。因此,您也可以写
target=${2:-}
告诉bash缺少的参数是OK的,应该作为空字符串处理。
即使是冗余的,如果不是打开-u
,使用${2:-}
显式显示你的意图,使你的程序更易于维护。