传递\ *作为参数的参数

时间:2015-10-23 00:53:03

标签: linux shell unix ksh

使用ksh。尝试重用当前脚本而不修改它,这基本上归结为这样的事情:

 `expr 5 $1 $2`

如何将乘法命令(*)作为参数$ 1传递?

我首先尝试使用“*”甚至是\ *,但这不起作用。 我尝试了多个转义反斜杠和引用组合,但我认为我做错了。

2 个答案:

答案 0 :(得分:3)

如果不修改脚本,我认为不能这样做

  • 调用时,您可以将文字*作为'*'"*"\*传递(任何人都可以):这将最初保护*免于shell扩展(由shell解释)。

  • callee (脚本)将接收文字*$1),但由于未加引号的使用脚本中的$1 *总是会受到文件名扩展(通配)的影响,并会扩展到当前文件夹中的所有(非隐藏)文件名,从而打破expr命令。

  • 尝试添加额外的转义层 - 例如"'*'"\\\* - 将无法正常工作,因为额外的转义将成为嵌入式,文字参数的一部分 - 目标脚本将看到文字 '*'\*并将原样传递给 expr,它将失败,因为它们都不是有效的运算符。

以下是解决方法

  • 更改为目录。
    • 默认情况下,如果没有匹配的文件名,ksh将返回任何glob(模式) as-is 。因此,*(或任何其他glob)将在 empty 目录中保持不变,因为没有什么可匹配的(谢谢,@Peter Cordes)。
    • 对于调用脚本/交互式shell,您可以通过运行set -f完全禁用globbing,但请注意,这不会影响调用的脚本。< / LI>
  • 现在使用'*'(或任何其他全局)调用脚本是安全的,因为它只是通过;例如,script '*' 2,现在将按预期产生10
    • 如果您从调用脚本shell的shell都是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)。

通常,除非你特别想要分词和全局扩展,否则总是引用它并不是一个坏习惯。