如何禁用bash中的特殊字符? [复制]

Posted

技术标签:

【中文标题】如何禁用bash中的特殊字符? [复制]【英文标题】:How to disable special characters in bash? [duplicate] 【发布时间】:2016-10-10 19:35:21 【问题描述】:

我创建了一个执行计算的脚本。例如: 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 本身,它会禁用特殊字符,但这不是我需要的)。还有一个shopt 命令可以控制shell 行为,所以我尝试启用一些选项,如shopt -s globstarnullglobpromptvars 等,但没有成功。我把命令放在 if 语句之前可能是错误的。

如果有人纠正我或告诉其他方式以禁用脚本内部对特殊字符的解释,我将不胜感激。

【问题讨论】:

当您运行count 1 * 3 时,* 将替换为在调用count 之前的文件名列表。这意味着count 不可能做任何事情来阻止它。替换发生在加载之前,甚至在磁盘上被识别。 好的,谢谢,那我得用另一种方式重写脚本了…… @Josh 我的回答包括另一种方式。 只使用单引号,一些shell函数示例:f() echo $(( $1 )) ; ,然后是f '2 * 32',打印64。首选 STDIN,执行:f() while read x ; do echo $(( $x )) ; done ; ,使用它来打印前十个阶乘:for x in $(seq 10) ; do seq -s'*' $x | f ; done 【参考方案1】:

当你回应时总是引用。您还需要引用变量引用:

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

【讨论】:

感谢您的宝贵时间。是的,我知道如果我写 2 '' 1 或 2 / 1 它会起作用,但我很好奇是否有办法只输入 2 * 2 而无需在命令行中使用转义字符。跨度> 【参考方案2】:

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

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

一些选项是:

要求一个引用参数的整个表达式,例如count "1 * 2"

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

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

这样可以避免外壳接触您的数据,以便您可以随意解释它。这就是 bcdc 所做的。

接受传递* 需要仔细引用的事实。

这就是expr 所做的。

使用magic alias hack,它只在特定情况下适用于某些 shell。

这是没有人会做的,因为它是脆弱且不可预测的,即使在某些情况下它允许你想要的语法。

【讨论】:

我以前从未见过那个神奇的别名破解;太可怕了!

以上是关于如何禁用bash中的特殊字符? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何对bash中的所有字符(特殊和非特殊)进行url编码[重复]

如何转义变量中的特殊字符以在 bash 中提供命令行参数

禁用 ExtJS 数字字段中的特殊字符

Bash 中的特殊字符大全

单引号是不是将反斜杠视为 bash 脚本中的特殊字符?

从bash中的字符串中删除所有特殊字符和大小写