![为什么这个相当简单的“如果”不起作用?](https://linux22.com/image/80294/%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E4%B8%AA%E7%9B%B8%E5%BD%93%E7%AE%80%E5%8D%95%E7%9A%84%E2%80%9C%E5%A6%82%E6%9E%9C%E2%80%9D%E4%B8%8D%E8%B5%B7%E4%BD%9C%E7%94%A8%EF%BC%9F.png)
这是我的脚本:
if [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] && [[ "$1" == "Decrypt" ]] || [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] && [[ "$1" == "Encrypt" ]]
then
key=aNXlye1tGbd0uP
else
if [ -z "$key" ]
then
key="$2"
fi
fi
它应该寻找第二个参数,删除电位.two
,然后将其与 进行比较load
,如果是load
,则应设置key
为aNXlye1tGbd0uP
。然而,这不起作用。这就是我运行它时的样子。
pskey Decrypt load (some string)
这是以下的输出bash -x
:
++ echo load
++ sed s/.two//g
+ [[ load == \l\o\a\d ]]
+ [[ Decrypt == \D\e\c\r\y\p\t ]]
+ [[ Decrypt == \E\n\c\r\y\p\t ]]
+ '[' -z '' ']'
+ key=load
但是,如果我删除之后的内容[[ "$1" == "Decrypt" ]]
,它就会起作用。那条线有什么问题吗?
答案1
如果我理解正确的话,你正在寻找这样的东西:
if [[ "$(echo "$2" | sed 's/.two//g')" == "load" && "$1" == "Decrypt" ]] ||
[[ "$(echo "$2" | sed 's/.two//g')" == "load" && "$1" == "Encrypt" ]]
then
...
fi
请注意,您还可以将整个事情简化为:
if [[ "$(echo "$2" | sed 's/.two//g')" == "load" && "$1" =~ (De|En)crypt ]]; then ...
答案2
terdon 的声明“这远非‘简单’ if
。”是轻描淡写。正如约翰·库格曼指出、
&&
和||
具有相同的优先级,并且从左到右处理。
BinaryZebra 提出了这个想法将布尔表达式转换为级联if
语句。我尽力“简化”
如果 A && B ||光盘 然后 结果=0 别的 结果=1 菲
是
如果一个 然后 如果 B 然后 如果D ← 然后 结果=0 别的 结果=1 菲 别的 如果C 然后 如果D 然后 结果=0 别的 结果=1 菲 别的 结果=1 菲 菲 别的 如果C 然后 如果D 然后 结果=0 别的 结果=1 菲 别的 结果=1 菲 菲
非常远从简单。从上面你可能可以看出,它不起作用的原因是,(在标记线上)如果 A 和 B 都为真,它仍然继续测试 D ( [[ "$1" == "Encrypt" ]]
)。
正如 BinaryZebra 所显示的,但没有提及,您能在 sh/bash 脚本中使用一些类似数学的符号;例如,你可以说
如果(A && B)|| (光盘) 然后 ︙
或者,在代码的稍微简化版本中,
如果([[“$2”==“加载”]] && [[“$1”==“解密”]]) || ([[“$2”==“加载”]] && [[“$1”==“加密”]]) 然后 ︙
其特点是括号中的代码在子 shell 中运行。如果这是一个问题,您可以使用大括号代替:
如果{[[“$2”==“加载”]] && [[“$1”==“解密”]]; } || {[[“$2”==“加载”]] && [[“$1”==“加密”]]; } 然后 ︙
注意,;
之前必须有一个}
(可以选择用空格分隔),并且之前和之后{
、之后都必须有空格}
。
当然,您应该使用其他答案中提出的技术简化你的测试,例如不是做两次相同的测试
$2
。
答案3
在你的代码中:
if [[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] &&
[[ "$1" == "Decrypt" ]] ||
[[ "$(echo "$2" | sed 's/.two//g')" == "load" ]] &&
[[ "$1" == "Encrypt" ]]
sed 调用可以简化为:${2%?two}
if 替换位于变量的末尾$2
。请理解,点(.)在 sed 中表示的“任何字符”相当于模式中的问号(?)(感谢@terdon)。如果需要对所有出现的 进行替换.two
,那么我们应该使用:"${2//?two}"
。然后我们得到这个较短的版本:
if [[ "${2//?two}" == "load" ]] && [[ "$1" == "Decrypt" ]] ||
[[ "${2//?two}" == "load" ]] && [[ "$1" == "Encrypt" ]]
这是在做什么if A && B || C && D
。
当 A 为真(load = load)时,B 被执行。如果 B 为真(Decrypt = Decrypt),则跳过
下面的短语 (C), 然后执行 D(Decrypt = Encrypt)。 其结果(最后执行的命令)为一个值。 然后执行......||
false
else
我怀疑你的意思是if ( A && B ) || ( C && D )
, as 与A
相同C
,与 完全相同if ( A && B ) || ( A && D )
,可以简化(使用分配财产) 到
if A && ( B || D )
:
if [[ "${2//?two}" == "load" ]] &&
( [[ "$1" == "Decrypt" ]] || [[ "$1" == "Encrypt" ]] );
then
key=aNXlye1tGbd0uP
else
if [ -z "$key" ]
then key="$2"
fi
fi
“$key”的测试-z
可以简化为简单的扩展:key="${key:-$2}"
而且,也许,它会更具可读性(IMO),如下所示:
if A; then
if B || D; then
翻译过来是这样的:
if [[ "${2//?two}" == "load" ]]
then if [[ "$1" == "Decrypt" ]] || [[ "$1" == "Encrypt" ]]
then key=aNXlye1tGbd0u
else key="${key:-$2}"
fi
else key="${key:-$2}"
fi
或者可以使用@terdon的想法,写成这样:
if [[ "${2//?two}" == "load" ]] &&
[[ "$1" =~ (De|En)crypt ]]
then key=aNXlye1tGbd0u
else key="${key:-$2}"
fi
请注意,这也是等效的:
if [[ ( "${2//?two}" == "load" ) &&
( "$1" =~ (De|En)crypt )
]]
then key=aNXlye1tGbd0u
else key="${key:-$2}"
fi
括号并不是严格必需的,但添加它是为了强制执行以下想法:在[[
测试内部,您可以为测试添加空白(制表符、空格、换行符)和括号,从而为测试提供结构。这在测试中效果不一样[
。
答案4
首先:
[[ $1:$2 =~ ^(En|De)crypt:(.two)*load(.two)*$ ]] && echo conditions met
但你的if
布尔逻辑是倒退的:
#sed #En=$1 #De=$1
true && false || true # passes your logic
true && true || NA # passes your logic
false && NA || false # fails your logic
false && NA || true # fails your logic
这里省略第二个&&
,因为它不是一个因素 - 它的结果始终与第一个相同。它在这个逻辑链中是一个无用的东西。
这不太有效——一个失败的案例打破了你的陈述。在第一个测试为假的任何情况下,您都会对其返回进行或运算,而不是 (De|En)crypt 测试。事实上,第一个甚至不会发生,因为它被短路了加载返回。因此,您需要首先执行 OR 运算,并通过延迟昂贵的命令替换来利用短路,直到您确实需要对其进行测试为止:
#En=$1 #De=$1 #sed
false || false && NA
false || true && false
false || true && true
true || NA && false
true || NA && true
所有这些都通过了您的逻辑,如果前两个语句都为假,则甚至不会尝试命令替换。
这是可移植的,带有case
和expr
:
case ${2%oad*}:${1%crypt} in
(:${key:=$2}*|*ad*|*:"$1") ;;
(*l:De|*l:En) expr " $2" : \
" \(\(.two\)*\(load\)*\)*$" &&
key=aNXlye1tGbd0uP
esac >/dev/null
和if
:
if [ Encrypt = "$1" -o Decrypt = "$1" ] &&
expr " $2" : " \(.two\)*load\(.two\)*$"
then key=$newkey
else key=${key:-$2}
fi >/dev/null
只是expr
和&&||
,因为if
对你来说没有多大作用:
expr > /dev/null \
"${#1} ${1%crypt} $2" :\
"7 \(\(De\)*\(En\)*\) ""\
\(.two\)*load\(.two\)*$" &&
key=$newkey || key=${key:-$2}
也许有grep
:
grep -xqE '(En|De)crypt:(.two)*load(.two)*' \
<<VAR && key=$newkey || key=${key:-$2}
${1##*:*}:$2
VAR