Perl Exec/System 传递参数

Perl Exec/System passing parameter

我对 perl (v5.26.3) 命令系统或 exec(两者具有相同的行为)有疑问

两个命令都可以正常工作

system ('git','pull','-ff','--no-rebase');
system ('git submodule --quiet foreach --recursive "echo ${name}"');

但是当我将“git 子模块”拆分为参数时:

system ('git','submodule','--quiet foreach','--recursive "echo ${name}"');

Perl returns:

usage: git submodule [--quiet] [--cached]
   or: git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
   or: git submodule [--quiet] status [--cached] [--recursive] [--] [<path>...]
   or: git submodule [--quiet] init [--] [<path>...]
   or: git submodule [--quiet] deinit [-f|--force] (--all| [--] <path>...)
   or: git submodule [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] [--] [<path>...]
   or: git submodule [--quiet] set-branch (--default|--branch <branch>) [--] <path>
   or: git submodule [--quiet] set-url [--] <path> <newurl>
   or: git submodule [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
   or: git submodule [--quiet] foreach [--recursive] <command>
   or: git submodule [--quiet] sync [--recursive] [--] [<path>...]
   or: git submodule [--quiet] absorbgitdirs [--] [<path>...]

如何传递参数?

对于获取列表的 system 调用,我们需要将命令传递给它,分成 words

If there is more than one argument in LIST, or if LIST is an array with more than one value, starts the program given by the first element of the list with arguments given by the rest of the list. If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is /bin/sh -c on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to execvp, ...

(我的重点)

让我们看一个简单的例子。接受像

这样的命令
ls -l --sort size dir "dir A" 

并将其分解,以便将“参数”列表传递给“命令”。没有命令 ls -l 但有 ls 及其参数 -l。也没有参数--sort size;有 --sort 个参数,和(它的值)size。但是用引号保护的东西,比如 "dir A",需要作为一个“令牌”传递。所以:('ls', '-l', '--sort', 'size', 'dir', 'dir A')

'--quiet foreach' 相同 -- that 说的是 git?

所以,不知道 git 命令,我会选择

system('git', 'submodule', '--quiet', 'foreach', '--recursive', '"echo ${name}"');

我原样保留 "echo ${name}" 因为我不知道它是什么意思。但这可能需要不同的写法,请澄清。


参见 man 3 exec

但它也很有启发性,也许更容易理解,看看 shell (bash) 是如何做到这一点的,一旦它 parses 给它一行。它是链接维基页面上的“第 6 步”,命令最终准备好传递给程序。


开始考虑——感谢 ikegami 的评论——目前还不清楚,虽然这确实很重要,但假设 $name 变量是......它属于谁。它是否需要在某个阶段进行推断,或者它是一个 git 需要按原样传递给 git 的东西?

这不会影响这个答案的整体要点:将命令分解为 单词 以传递给 system 对 LIST 的调用。这意味着基本上用 space 来打破它,除了 space 被转义的部分(就像它有效地用引号)。

(另请参阅 exec 页面,至少了解在只有一个参数但我们仍想避免 shell 的情况下如何使用 LIST 调用。)