将 \* 作为参数传递给参数
Passing \* as a parameter for a parameter
使用 ksh。尝试重用当前脚本而不修改它,基本上可以归结为这样的事情:
`expr 5 `
如何将乘法命令 (*) 作为参数 $1 传递?
我首先尝试使用“*”,甚至是 \*,但没有用。
我尝试了多个转义反斜杠和引号组合,但我认为我做错了。
不修改脚本,我觉得做不到:
在调用时,您可以将文字*
作为'*'
、"*"
或[=13=传递](任何人都可以):这将 最初 保护 *
免受 shell 扩展(由 shell 解释)。
被调用者(脚本)随后将接收文字 *
(如 </code>),但由于 <em>unquoted</em> 在脚本中使用 <code>
,*
将不可避免地受到文件名扩展(globbing)的影响,并将扩展到所有当前文件夹中的(非隐藏)文件名,打破了 expr
命令。
尝试添加额外的转义层 - 例如 "'*'"
或 \\*
- 将不起作用,因为额外的转义将成为参数的 embedded, literal 部分 - 目标脚本将看到 literal '*'
或 \*
和将它 按原样 传递给 expr
,这将失败,因为两者都不是有效的运算符。
这是一个解决方法:
- 更改为空 目录。
- 默认情况下,如果没有匹配的文件名,
ksh
将 return 任何 glob(模式)原样。因此,*
(或任何其他 glob)将在 空 目录中保持不变,因为没有任何匹配项(感谢,@Peter Cordes)。
- 对于调用脚本/交互shell,您可以通过运行
set -f
完全禁用globbing,但请注意,这不会影响 调用的 脚本。
- 现在可以安全地使用
'*'
(或任何其他 glob)调用您的脚本,因为它会被简单地传递;例如,script '*' 2
,现在将按预期产生 10
- 如果您从 调用的 shell 和 脚本的 shell 都是
ksh
(或 bash
)默认配置,你甚至可以摆脱 script * 2
;即,您可以不完全引用 *
。
Glob 扩展发生得非常晚,在参数扩展和分词(按此顺序)之后。引号删除不会发生在早期扩展的结果上,只是在命令行上开始。这排除了通过使用额外的引号层来传递带引号的 \*
或类似的(参见 mklement0 的回答)。
它还排除了传入 space-padded *
:分词删除了路径名(glob)扩展之前的 spaces,所以它最终仍然扩展 *
到目录中的所有文件名。
foo(){ printf '"%s"\n' "$@"; set -x; expr 5 ; set +x; }
$ foo ' * ' 4
" * "
"4"
+ expr 5 ...contents of my directory... 4
expr: syntax error
+ set +x
您应该在有人使用以危险方式破坏它的 arg 而不仅仅是不方便的 arg 运行它之前修复这个有问题的脚本。
如果您不需要支持与 expr
完全相同的运算符,您可能希望使用算术扩展来实现,而无需 运行 外部命令:
result=$((5 )) # arithmetic expansion for the right-hand side
# or
((result=5 "" "")) # whole command is an arithmetic expression.
参数周围的双引号在算术表达式中是可选的,但您不需要在算术扩展中使用它们(在 bash 中。显然这在 ksh 中有效)。
通常情况下,总是引用并不是一个坏习惯,除非你特别想要分词和 glob 扩展。
使用 ksh。尝试重用当前脚本而不修改它,基本上可以归结为这样的事情:
`expr 5 `
如何将乘法命令 (*) 作为参数 $1 传递?
我首先尝试使用“*”,甚至是 \*,但没有用。 我尝试了多个转义反斜杠和引号组合,但我认为我做错了。
不修改脚本,我觉得做不到:
在调用时,您可以将文字
*
作为'*'
、"*"
或[=13=传递](任何人都可以):这将 最初 保护*
免受 shell 扩展(由 shell 解释)。被调用者(脚本)随后将接收文字
*
(如</code>),但由于 <em>unquoted</em> 在脚本中使用 <code>
,*
将不可避免地受到文件名扩展(globbing)的影响,并将扩展到所有当前文件夹中的(非隐藏)文件名,打破了expr
命令。尝试添加额外的转义层 - 例如
"'*'"
或\\*
- 将不起作用,因为额外的转义将成为参数的 embedded, literal 部分 - 目标脚本将看到 literal'*'
或\*
和将它 按原样 传递给expr
,这将失败,因为两者都不是有效的运算符。
这是一个解决方法:
- 更改为空 目录。
- 默认情况下,如果没有匹配的文件名,
ksh
将 return 任何 glob(模式)原样。因此,*
(或任何其他 glob)将在 空 目录中保持不变,因为没有任何匹配项(感谢,@Peter Cordes)。 - 对于调用脚本/交互shell,您可以通过运行
set -f
完全禁用globbing,但请注意,这不会影响 调用的 脚本。
- 默认情况下,如果没有匹配的文件名,
- 现在可以安全地使用
'*'
(或任何其他 glob)调用您的脚本,因为它会被简单地传递;例如,script '*' 2
,现在将按预期产生10
- 如果您从 调用的 shell 和 脚本的 shell 都是
ksh
(或bash
)默认配置,你甚至可以摆脱script * 2
;即,您可以不完全引用*
。
- 如果您从 调用的 shell 和 脚本的 shell 都是
Glob 扩展发生得非常晚,在参数扩展和分词(按此顺序)之后。引号删除不会发生在早期扩展的结果上,只是在命令行上开始。这排除了通过使用额外的引号层来传递带引号的 \*
或类似的(参见 mklement0 的回答)。
它还排除了传入 space-padded *
:分词删除了路径名(glob)扩展之前的 spaces,所以它最终仍然扩展 *
到目录中的所有文件名。
foo(){ printf '"%s"\n' "$@"; set -x; expr 5 ; set +x; }
$ foo ' * ' 4
" * "
"4"
+ expr 5 ...contents of my directory... 4
expr: syntax error
+ set +x
您应该在有人使用以危险方式破坏它的 arg 而不仅仅是不方便的 arg 运行它之前修复这个有问题的脚本。
如果您不需要支持与 expr
完全相同的运算符,您可能希望使用算术扩展来实现,而无需 运行 外部命令:
result=$((5 )) # arithmetic expansion for the right-hand side
# or
((result=5 "" "")) # whole command is an arithmetic expression.
参数周围的双引号在算术表达式中是可选的,但您不需要在算术扩展中使用它们(在 bash 中。显然这在 ksh 中有效)。
通常情况下,总是引用并不是一个坏习惯,除非你特别想要分词和 glob 扩展。