bash 使用大括号参数列表多次执行命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13971808/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 04:03:55  来源:igfitidea点击:

Execute command multiple times with curly brackets arguments list

bashshellcommand-linecommand-line-argumentsbrace-expansion

提问by Haralan Dobrev

When I needed to run a command multiple times with a different argument I used this approach (without understanding it fully):

当我需要使用不同的参数多次运行命令时,我使用了这种方法(没有完全理解它):

touch {a,b,c}

Which is equivalent of:

这相当于:

touch a
touch b
touch c

I think the same could be accomplished with the following loop:

我认为同样可以通过以下循环来完成:

for file in {a,b,c}; do touch $file; done

However I've stumbled across a case where this does not work:

但是,我偶然发现了一个不起作用的情况:

pear channel-discover {"pear.phpunit.de","pear.symfony-project.com"}

I have a few questions:

我有几个问题:

  1. What is the name of what is happening in the first example and what exactly is happening?
  2. Is it better to use this approach for simple things rather than for-in loops?
  3. Why the pear command is not working like that? Should the command script implement some techniques to handle such arguments or is it the shell responsible for that?
  1. 第一个示例中发生的事情的名称是什么,究竟发生了什么?
  2. 将这种方法用于简单的事情而不是 for-in 循环更好吗?
  3. 为什么 pear 命令不能这样工作?命令脚本是否应该实现一些技术来处理这些参数,还是由 shell 负责?

回答by Shawn Chin

That's called Brace Expansion, which expands to a space-separated list of the given strings.

这称为Brace Expansion,它扩展为给定字符串的空格分隔列表。

So touch {a,b,c}would be equivalent to

所以touch {a,b,c}将相当于

touch a b c

While touch {a,b,c}xwould be equivalent to:

虽然touch {a,b,c}x相当于:

touch ax bx cx

You pearcommand would essentially be run as:

您的pear命令基本上将运行为:

pear channel-discover pear.phpunit.de pear.symfony-project.com

which may not be what you expected. If you want the command to be run once for each string, use a for loop (which answers your 2nd question), or use a combination of brace expansion and xargs.

这可能不是您所期望的。如果您希望命令为每个字符串运行一次,请使用 for 循环(它回答您的第二个问题),或使用大括号扩展和 xargs 的组合。

回答by Jens

The problem is that contrary to your expectation, the brace expansionof

问题是,违背你的期望,在括号扩展

touch {a,b,c}

is equivalent to

相当于

touch a b c   # NOT 3 separate invocations.

(Use echo {a,b,c}to verify). It appears that pear channel-discoverdoes not accept twoargs. You will probably see the same error with

echo {a,b,c}用于验证)。似乎pear channel-discover不接受两个参数。您可能会看到相同的错误

pear channel-discover pear.phpunit.de pear.symfony-project.com

回答by yo'

Well, you have two options:

那么,你有两个选择:

for i in "pear.phpunit.de" "pear.symfony-project.com"
do
  pear channel-discover "$i"
done

Or a one-liner (but calling xargsinstead of using bash internals):

或单行(但调用xargs而不是使用 bash 内部结构):

echo "pear.phpunit.de" "pear.symfony-project.com" | xargs -n1 pear channel-discover

The former is certainly easier to read by the human, the time efficiency will be basically the same.

前者当然更容易被人类阅读,时间效率会基本相同。