如何在shell(sh,bash等)中将多个命令传输到单个命令中?

78

我该如何将多个命令的标准输出重定向到单个命令中?

示例1:将所有三个echo命令的输出合并并排序:

echo zzz; echo aaa; echo kkk

期望的输出:

aaa
kkk
zzz

示例2:使用管道将所有命令放入单个命令行中,而无需重定向到临时文件:

setopt > /tmp/foo; unsetopt >> /tmp/foo; set >> /tmp/foo; sort /tmp/foo
3个回答

110
使用括号()将命令组合成一个单一的进程,这将连接每个命令的标准输出。
示例1(注意,$是shell提示符):
$ (echo zzz; echo aaa; echo kkk) | sort
aaa
kkk
zzz

Example 2:
$ (setopt; unsetopt; set) | sort

9
@glenn:这并不重要(在bash 3.2.48版本中已测试),因为管道强制将其放入子shell中。 - Gordon Davisson
3
请查看“管道”部分(https://www.gnu.org/software/bash/manual/bash.html#Pipelines):“管道中的每个命令都在其自己的子Shell中执行...”。实际上,可以使用 shopt -s lastpipe 来更改这一点,它会在当前Shell中运行管道的最后一部分。但是在这种情况下,我们关心的是第一部分,因此它仍将在子Shell中运行。 - Gordon Davisson
3
在bash下,它似乎将它们合并成一个子shell层级(至少在版本2.05b.0、3.2.57和4.2.10中测试;其他shell可能会有所不同)。但是当我使用“{(echo zzz; echo aaa; echo kkk)} | sort”时,确实会得到额外的子shell。 - Gordon Davisson

29

您可以使用{}来实现此操作,而不需要像(list)那样使用子Shell,操作如下:

{ echo zzz; echo aaa; echo kkk; } | sort

{之后和}之前,我们确实需要一个空格字符。如果在单行上编写该序列,则还需要最后一个;

我们还可以将其分成多行而不需要任何;

示例1:

{
  echo zzz
  echo aaa
  echo kkk
} | sort

例子2:

{
  setopt
  unsetopt
  set
} | sort

3
在Windows中,它应该是这样的:(echo zzz & echo aaa & echo kkk) | sort 或者如果它在批处理文件中,它可以是单行(就像样例一样)也可以是多行:
(
 echo zzz
 echo aaa
 echo kkk
) | sort

注意:原帖未提到此方法仅适用于Linux,因此我添加了Windows命令行的解决方案...当使用脚本内的diskpart(echo diskpart_command)与VHD/VHDX一起工作时,它非常有用,而不是在同一行上使用echo,但要保留echo,还有另一种方法可以不使用echo而使用>重定向器,但容易出错且更加复杂(如果存在一个简单的方法始终正常工作,为什么要使用一个复杂的容易出错的方式)...还要记住,%d%给出了实际路径(对于不硬编码VHD/VHDX文件路径非常有用)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接