如何禁用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 globstar
、nullglob
、promptvars
等,但没有成功。我把命令放在 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
。
这样可以避免外壳接触您的数据,以便您可以随意解释它。这就是 bc
和 dc
所做的。
接受传递*
需要仔细引用的事实。
这就是expr
所做的。
使用magic alias hack,它只在特定情况下适用于某些 shell。
这是没有人会做的,因为它是脆弱且不可预测的,即使在某些情况下它允许你想要的语法。
【讨论】:
我以前从未见过那个神奇的别名破解;太可怕了!以上是关于如何禁用bash中的特殊字符? [复制]的主要内容,如果未能解决你的问题,请参考以下文章