这是你的选择。如果您不引用$@
任何值,则将对其进行进一步的扩展和解释。如果确实引用了它,则传递给该函数的所有参数都将按其扩展原样复制。如果&>|
不自己解析参数,您将永远无法可靠地处理诸如此类之类的shell语法标记-因此,您将只有更合理的选择来处理函数之一:
- 确切地说,是在执行单个简单命令时使用的单词
"$@"
。
...要么...
- 参数的进一步扩展和解释的版本,然后将这些参数作为简单命令一起应用
$@
。
如果这是故意的,并且您所选择的效果得到了很好的理解,那么这两种方法都不对。尽管第二种方法的优点很少特别有用,但这两种方法都具有另一种优点。仍然...
(run_this(){ $@; }; IFS=@ run_this 'ls@-dl@/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
...这不是没有用的,只是很少会有用。而在一个bash
壳,因为bash
在默认情况下不沾,即使所述限定前置到一个特殊的内置的命令行或函数的变量定义它的环境,为全球价值$IFS
不受影响,它的声明是本地只给run_this()
电话。
类似地:
(run_this(){ $@; }; set -f; run_this ls -l \*)
ls: cannot access *: No such file or directory
...也可以配置。行情是有目的的-它们并非一无是处。没有它们,外壳扩展将进行额外的解释-可配置的解释。它曾经是-有一些非常古老贝壳-这$IFS
是全球范围内应用到所有的输入,而不仅仅是扩展。实际上,所说的shell的行为非常相似run_this()
,因为它们破坏了值的所有输入单词$IFS
。因此,如果您要查找的是旧的shell行为,则应使用run_this()
。
我不是在寻找它,现在我很难找到一个有用的例子。我通常更喜欢我的shell运行的命令是我键入的命令。因此,只要有选择,我几乎都会run_that()
。除了那个...
(run_that(){ "$@"; }; IFS=l run_that 'ls' '-ld' '/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
几乎任何东西都可以引用。命令将用引号引起来。之所以起作用,是因为到命令实际运行时,所有输入词都已经被删除了引号 -这是Shell输入解释过程的最后阶段。因此,'ls'
和之间的区别ls
仅在解释外壳程序时才重要-这就是为什么引用ls
确保任何命名的别名ls
都不能代替我引用的ls
命令字的原因。除此之外,引用的唯一影响是单词的定界(这是变量/输入空格引用的工作方式和原因)以及元字符和保留字的解释。
所以:
'for' f in ...
do :
done
bash: for: command not found
bash: do: unexpected token 'do'
bash: do: unexpected token 'done'
您将永远无法使用run_this()
或来做到这一点run_that()
。
但是函数名称,$PATH
'd命令或内建函数将只用引号引起来或不加引号,这就是方法run_this()
和run_that()
工作的最开始。您将无法对$<>|&(){}
任何这些做任何有用的事情。不到eval
,是。
(run_that(){ "$@"; }; run_that eval printf '"%s\n"' '"$@"')
eval
printf
"%s\n"
"$@"
但是如果没有它,您将由于使用的引号而受制于一个简单命令的限制(即使您不这样做,因为$@
当解析元字符的命令时,其行为就像过程开始时的引号一样)。命令行分配和重定向受到相同的约束,它们仅限于函数的命令行。但这没什么大不了的:
(run_that(){ "$@";}; echo hey | run_that cat)
hey
我可以像打开管道一样轻松地<
重定向输入或>
输出。
无论如何,在这里没有回旋的对与错的方法-每种方法都有其用途。只是您应该在打算使用它时编写它,并且应该知道要做什么。省略引号可以有目的-否则根本就不会有引号-但是如果您出于与目的不相关的原因而省略了引号,则您只是在编写错误的代码。按照你的意思去做 我还是尝试。
run_that
的行为肯定是我所期望的(命令路径中是否有空格?)。如果您想要其他行为,请确保在您知道数据是什么的呼叫站点取消报价。我希望将此函数称为run_that ls -l
,在任何一个版本中其效果都相同。有没有让您期望不同的情况?