使用ksh。尝试重用当前脚本而不修改它,这基本上归结为这样的事情:
`expr 5 $1 $2`
如何将乘法命令(*)作为参数$ 1传递?
我首先尝试使用“*”甚至是\ *,但这不起作用。 我尝试了多个转义反斜杠和引用组合,但我认为我做错了。
答案 0 :(得分:3)
如果不修改脚本,我认为不能这样做:
在调用时,您可以将文字*
作为'*'
,"*"
或\*
传递(任何人都可以):这将最初保护*
免于shell扩展(由shell解释)。
callee (脚本)将接收文字*
($1
),但由于未加引号的使用脚本中的$1
,*
总是会受到文件名扩展(通配)的影响,并会扩展到当前文件夹中的所有(非隐藏)文件名,从而打破expr
命令。
尝试添加额外的转义层 - 例如"'*'"
或\\\*
- 将无法正常工作,因为额外的转义将成为嵌入式,文字参数的一部分 - 目标脚本将看到文字 '*'
或\*
并将原样传递给 expr
,它将失败,因为它们都不是有效的运算符。
以下是解决方法:
ksh
将返回任何glob(模式) as-is 。因此,*
(或任何其他glob)将在 empty 目录中保持不变,因为没有什么可匹配的(谢谢,@Peter Cordes)。set -f
完全禁用globbing,但请注意,这不会影响调用的脚本。< / LI>
'*'
(或任何其他全局)调用脚本是安全的,因为它只是通过;例如,script '*' 2
,现在将按预期产生10
ksh
(或bash
)并使用默认配置,那么您甚至可以使用{{1} };也就是说,你可以完全不引用script * 2
。答案 1 :(得分:2)
在参数扩展和单词拆分(按此顺序)后,Glob扩展很晚发生。引用删除不会发生在早期扩展的结果上,只是命令行上的内容开始。这通过使用额外的引用层来排除引用引用\*
或类似内容(请参阅mklement0&#39;答案)。
它还排除了在空格填充*
中的传递:字词拆分在路径名(glob)扩展之前删除了空格,因此它仍然最终将*
扩展到目录中的所有文件名。
foo(){ printf '"%s"\n' "$@"; set -x; expr 5 $1 $2; set +x; }
$ foo ' * ' 4
" * "
"4"
+ expr 5 ...contents of my directory... 4
expr: syntax error
+ set +x
你应该修复这个有问题的脚本,然后才会有人用一个以危险的方式打破它的arg运行它,而不仅仅是不方便。
如果您不需要支持与expr
完全相同的运算符,则可能需要使用算术扩展来执行此操作而不运行外部命令:
result=$((5 $1 $2)) # arithmetic expansion for the right-hand side
# or
((result=5 "$1" "$2")) # whole command is an arithmetic expression.
参数的双引号在算术表达式中是可选的,但您不需要在算术扩展中使用它们(在bash中。显然这适用于ksh)。
通常,除非你特别想要分词和全局扩展,否则总是引用它并不是一个坏习惯。