有这样的方法吗
int a = (b == 5) ? c : d;
使用Bash ?
有这样的方法吗
int a = (b == 5) ? c : d;
使用Bash ?
当前回答
还有两个答案
这里有一些思考的方法
Bash整数变量
此外,dutCh, Vladimir和ghostdog74的纠正答案,因为这个问题是关于整数和带标签的bash:
有这样的方法吗 Int a = (b == 5) ?C: d;
在bash下使用整数有一个很好的方法:
declare -i b=' RANDOM % 3 + 4 ' c=100 d=50 a=' b == 5 ? c : d '; echo $b '-->' $a
这个命令的输出行应该是:
4 --> 50
5 --> 100
6 --> 50
当然,声明整型变量只需要执行一次:
declare -i a b c d
c=100 d=50 b=RANDOM%3+4
a=' b == 5 ? c : d '
echo $a $b
100 5
b=12 a=b==5?c:d
echo $a $b
50 12
题外话:使用字符串作为数学函数:
mathString=' b == 5 ? c : d '
b=5 a=$mathString
echo $a $b
100 5
b=1 a=$mathString
echo $a $b
50 1
基于参数展开和间接
以下是Brad Parks和druid62的回答,这里有一种不局限于整数的方法:
c=50 d=100 ar=([5]=c)
read -p 'Enter B: ' b
e=${ar[b]:-d};echo ${!e}
如果b==5,那么ar[b]是c,间接做c是50。 否则ar[除5之外的任何值]为空,因此参数展开将默认为d,其中间接给出100。
同样的演示使用数组代替整数
ternArrayDemo(){
local -a c=(foo bar) d=(foo bar baz) e=(empty) ar=([5]=c [2]=d)
local b=${ar[$1]:-e}
b+=[@] # For array indirection
printf ' - %s\n' "${!b}"
}
Then
ternArrayDemo 0
- empty
ternArrayDemo 2
- foo
- bar
- baz
ternArrayDemo 4
- empty
ternArrayDemo 5
- foo
- bar
ternArrayDemo 6
- empty
或者使用关联数组
ternAssocArrayDemo(){
local -a c=(foo bar) d=(foo bar baz) e=(empty)
local -A ar=([foo]=c[@] [bar]=d[@] [baz]=d[-1])
local b=${ar[$1]:-e[@]}
printf ' - %s\n' "${!b}"
}
Then
ternAssocArrayDemo hello
- empty
ternAssocArrayDemo foo
- foo
- bar
ternAssocArrayDemo bar
- foo
- bar
- baz
ternAssocArrayDemo baz
- baz
其他回答
在bash中还有一个非常相似但更简单的三元条件语句语法:
a=$(( b == 5 ? 123 : 321 ))
(( a = b==5 ? c : d )) # string + numeric
这是通解
也适用于字符串测试 感觉更像是一种表达 避免在条件失效时产生任何微妙的副作用
数值比较试验
a=$(if [ "$b" -eq 5 ]; then echo "$c"; else echo "$d"; fi)
字符串比较测试
a=$(if [ "$b" = "5" ]; then echo "$c"; else echo "$d"; fi)
代码:
a=$([ "$b" == 5 ] && echo "$c" || echo "$d")
上面的答案[[$b = 5]] && a="$c" || a="$d"应该只在你确定&&之后没有错误的情况下使用,否则它将错误地执行||之后的部分。
为了解决这个问题,我写了一个三元函数,它的行为应该,它甚至使用?和:操作符:
编辑-新的解决方案
这是我的新解决方案,不使用$IFS或ev(a/i)l。
function executeCmds()
{
declare s s1 s2 i j k
declare -A cmdParts
declare pIFS=$IFS
IFS=$'\n'
declare results=($(echo "$1" | grep -oP '{ .*? }'))
IFS=$pIFS
s="$1"
for ((i=0; i < ${#results[@]}; i++)); do
s="${s/${results[$i]}/'\0'}"
results[$i]="${results[$i]:2:${#results[$i]}-3}"
results[$i]=$(echo ${results[$i]%%";"*})
done
s="$s&&"
let cmdParts[t]=0
while :; do
i=${cmdParts[t]}
let cmdParts[$i,t]=0
s1="${s%%"&&"*}||"
while :; do
j=${cmdParts[$i,t]}
let cmdParts[$i,$j,t]=0
s2="${s1%%"||"*};"
while :; do
cmdParts[$i,$j,${cmdParts[$i,$j,t]}]=$(echo ${s2%%";"*})
s2=${s2#*";"}
let cmdParts[$i,$j,t]++
[[ $s2 ]] && continue
break
done
s1=${s1#*"||"}
let cmdParts[$i,t]++
[[ $s1 ]] && continue
break
done
let cmdParts[t]++
s=${s#*"&&"}
[[ $s ]] && continue
break
done
declare lastError=0
declare skipNext=false
for ((i=0; i < ${cmdParts[t]}; i++ )) ; do
let j=0
while :; do
let k=0
while :; do
if $skipNext; then
skipNext=false
else
if [[ "${cmdParts[$i,$j,$k]}" == "\0" ]]; then
executeCmds "${results[0]}" && lastError=0 || lastError=1
results=("${results[@]:1}")
elif [[ "${cmdParts[$i,$j,$k]:0:1}" == "!" || "${cmdParts[$i,$j,$k]:0:1}" == "-" ]]; then
[ ${cmdParts[$i,$j,$k]} ] && lastError=0 || lastError=1
else
${cmdParts[$i,$j,$k]}
lastError=$?
fi
if (( k+1 < cmdParts[$i,$j,t] )); then
skipNext=false
elif (( j+1 < cmdParts[$i,t] )); then
(( lastError==0 )) && skipNext=true || skipNext=false
elif (( i+1 < cmdParts[t] )); then
(( lastError==0 )) && skipNext=false || skipNext=true
fi
fi
let k++
[[ $k<${cmdParts[$i,$j,t]} ]] || break
done
let j++
[[ $j<${cmdParts[$i,t]} ]] || break
done
done
return $lastError
}
function t()
{
declare commands="$@"
find="$(echo ?)"
replace='?'
commands="${commands/$find/$replace}"
readarray -d '?' -t statement <<< "$commands"
condition=${statement[0]}
readarray -d ':' -t statement <<< "${statement[1]}"
success="${statement[0]}"
failure="${statement[1]}"
executeCmds "$condition" || { executeCmds "$failure"; return; }
executeCmds "$success"
}
executeCmds将每个命令单独分开,除了由于&&和||操作符而应该跳过的命令。当命令以!开头时,它使用[]。或者一面旗帜。
向它传递命令有两种方式:
传递单个命令时不加引号,但一定要引用;、&&和||操作符。
t ls / ? ls qqq '||' echo aaa : echo bbb '&&' ls qq
传递所有引用的命令:
t 'ls /a ? ls qqq || echo aaa : echo bbb && ls qq'
注意,我发现没有办法将&&和||操作符作为不带引号的参数传递,因为它们是函数名和别名的非法字符,我也没有办法覆盖bash操作符。
旧的解决方案-使用ev(a/i)l
function t()
{
pIFS=$IFS
IFS="?"
read condition success <<< "$@"
IFS=":"
read success failure <<< "$success"
IFS=$pIFS
eval "$condition" || { eval "$failure" ; return; }
eval "$success"
}
t ls / ? ls qqq '||' echo aaa : echo bbb '&&' ls qq
t 'ls /a ? ls qqq || echo aaa : echo bbb && ls qq'