我创建了一个执行计算的脚本。例如:
count 1 + 3
1 + 3 = 4
,
-
和/
也有效,但如果我输入
算1 * 3
,我得到了
应为数字操作数编号
以下是脚本的一部分:
if [ "$#" -ne 3 ]; then
echo "Should be number operand number"
exit 1
fi
...
elif [ "$2" = "*" ]; then
result=`echo $1 \* $3 | bc`
echo "$1 * $3 = $result"
是的,如果我在\
之前在命令行中键入*
它会起作用,但我需要它只使用*
运行。
我试过在它不起作用的脚本中使用set -f
(是的,如果我输入bash本身但它不是我需要的话,它会禁用特殊字符)。还有一个控制shell行为的shopt
命令,所以我尝试启用一些选项,例如shopt -s globstar
,nullglob
,promptvars
等。它不起作用。我之前把命令放在if语句可能是错的。
如果有人纠正我或者告诉另一种方法禁止从剧本内部解释特殊字符,我将不胜感激。
答案 0 :(得分:2)
POSIX specification of expr中提到了这个确切的问题,因为您所描述的原因,该工具具有“相当困难的语法”。
这绝对是一个已知的问题,换句话说,POSIX本身就没有解决它。你应该考虑使用Unix并做同样的事情,而不是试图反对它。
有些选择是:
要求整个表达式为一个带引号的参数,例如: count "1 * 2"
这是一种务实,快速的方法,可以确保始终引用参数,因此*的任何引入仍然有效。 bash builtin let
执行此操作。
read
表达自己,例如只需运行count
,然后输入1 * 2
。
这可以避免shell触摸您的数据,以便您可以根据需要进行解释。这是bc
和dc
所做的。
实际上传递*
需要仔细引用。
这是expr
的作用。
使用仅在特定情况下适用于某些炮弹的magic alias黑客。
这是没有人做的,因为它很脆弱且不可预测,即使它在某些情况下允许你想要的语法。
答案 1 :(得分:0)
当你回声时总是引用。您还需要引用变量引用:
me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR
如果您不使用双引号,则bash会看到*
并执行filename expansion。 *
扩展到当前目录中的所有文件。
但是在说这个时你必须使用*
的单引号:
#!/bin/bash
if [ "$2" = "*" ]; then
result=`echo $1 \* $3 | bc`
echo "$1 * $3 = $result"
fi
以下方法可行:
» count.sh 2 '*' 1
2 * 2 = 4
您的程序中无法执行任何操作,因为*
扩展由shell完成(与Windows相比,程序完成此操作)。
以下是使用菜单驱动方式的另一个code example:
#!/bin/bash
while true; do
read -p "what's the first number? " n1
read -p "what's the second number? " n2
PS3="what's the operation? "
select ans in add subtract multiply divide; do
case $ans in
add) op='+' ; break ;;
subtract) op='-' ; break ;;
multiply) op='*' ; break ;;
divide) op='/' ; break ;;
*) echo "invalid response" ;;
esac
done
ans=$(echo "$n1 $op $n2" | bc -l)
printf "%s %s %s = %s\n\n" "$n1" "$op" "$n2" "$ans"
done
what's the first number? 5
what's the second number? 4
1) add
2) subtract
3) multiply
4) divide
what's the operation? /
invalid response
what's the operation? 4
5 / 4 = 1.25000000000000000000
简而言之,引用您不需要shell执行令牌拆分和通配符扩展的所有内容。