为什么在Bash中你需要引用?

时间:2017-05-13 06:24:38

标签: bash unix

    if [ "$a" -gt "$b" ]; then
    ...
    fi

为什么我不能拥有:

if [ $a -gt $b ]; then
        ...
        fi

对于Bash?

3 个答案:

答案 0 :(得分:1)

算术运算符-gt(大于)$a$b必须包含整数,且不需要引号。

答案 1 :(得分:1)

此处需要引号进行更正 - 例如,避免代码注入。让我们说你的脚本没有引用,你让我输入数字告诉我哪一个更大。

我输入:

a="1"
b="1 -o -e /home/foo"

由于您没有引用,您现在正在评估

[ 1 -gt 1 -o -e /home/foo ]

并告诉我,如果b存在,/home/foo会更大。

您的号码比较脚本突然变成了一个简单的文件浏览器,我可以用它来检查您的系统,以查找活动用户,运行进程,安装的软件,硬件配置等。

这在实践中可能无关紧要,但如果它很容易做到正确,你也可以引用。

答案 2 :(得分:1)

TL; DR

您未提供任何示例输入,但您的变量可能未设置,为空或不包含整数。为了使您的脚本更加健壮,您应该始终引用变量,测试空或未设置变量等条件,或者如果您不能保证变量的内容或消耗用户输入,则执行其他验证。

无效扩展

除非您已将变量明确声明为整数,有时甚至在您做的时候,否则有几种情况您的比较无效。例如:

    public static BufferedImage textToImage(String text, Font font, int bottomPadding, Color color, BufferedImage background) {
    int width = background.getGraphics().getFontMetrics(font).stringWidth(text);
    int height = background.getGraphics().getFontMetrics(font).getHeight();
    BufferedImage bufferedImage = new BufferedImage(width, height, TYPE_4BYTE_ABGR);
    Graphics2D graphics = bufferedImage.createGraphics();
    graphics.setBackground(new Color(0f, 0f, 0f, .0f)); //transparent
    graphics.setColor(color);
    graphics.setFont(font);
    graphics.drawString(text, 0, height - bottomPadding);
    graphics.dispose();
    return bufferedImage;
}

您有许多选项,但最简单的方法是使用Bash表达式运算符而不是实际上等同于 / bin / test 的单括号。这可以更优雅地处理空扩展和其他用例。例如:

$ unset a b; a=1; [ $a -gt $b ]
-bash: [: 1: unary operator expected

将变量声明为整数可能帮助

但是,你仍然需要注意意外的演员阵容。例如:

# Here, *b* is unset so *a* is "greater."
$ unset a b; a=1; [[ $a -gt $b ]]; echo $?
0

# This time *a* is unset, so the expression is false.
$ unset a b; b=1; [[ $a -gt $b ]]; echo $?
1

更好的是使用$ unset a b; a='foo'; b='1'; [[ $a -gt $b ]]; echo $? 1 $ echo $a foo 来强制进行整数转换,但如果您不验证输入,这仍会导致意外结果。例如:

declare -i

通过声明变量,强制值为整数,但字符串将被指定为零。这可能不是您所期望的。

验证和防御性报价

虽然简单的脚本有点过分,但这是一个更健壮的脚本。

$ unset a b; declare -i a='foo' b='1'; [[ $a -gt $b ]]; echo $?
1

$ echo $a
0

请注意,在这种情况下,引号和括号并非绝对必要,但是可以显示出良好的防御性编程。你可以通过自由使用它们在Bash中出错,而且它们通常会为你节省大量的头脑和调试。