如何禁用bash中的特殊字符?

时间:2016-06-09 23:55:26

标签: bash shell special-characters positional-parameter

我创建了一个执行计算的脚本。例如: 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 globstarnullglobpromptvars等。它不起作用。我之前把命令放在if语句可能是错的。

如果有人纠正我或者告诉另一种方法禁止从剧本内部解释特殊字符,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

POSIX specification of expr中提到了这个确切的问题,因为您所描述的原因,该工具具有“相当困难的语法”。

这绝对是一个已知的问题,换句话说,POSIX本身就没有解决它。你应该考虑使用Unix并做同样的事情,而不是试图反对它。

有些选择是:

  • 要求整个表达式为一个带引号的参数,例如: count "1 * 2"

    这是一种务实,快速的方法,可以确保始终引用参数,因此*的任何引入仍然有效。 bash builtin let执行此操作。

  • read表达自己,例如只需运行count,然后输入1 * 2

    这可以避免shell触摸您的数据,以便您可以根据需要进行解释。这是bcdc所做的。

  • 实际上传递*需要仔细引用。

    这是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执行令牌拆分和通配符扩展的所有内容。