管道输出到标准输出然后到命令然后到变量

pipe output to stdout and then to command then to variable

我在 TeamCity 服务器上工作,我的构建命令之一是:

xcodebuild -scheme "<myscheme>" archive

我需要检索 .dSYM 文件

code=$(cat <<-'CODE'
$lines = file("php://stdin");
foreach($lines as $line){
  if(preg_match("#Touch (.*dSYM)#",$line,$m))echo "$m[1]\n";
}
CODE
)
dsym=$(xcodebuild -scheme "<myscheme>" archive | php -r "$code")

这行得通。但是,我的问题是,我希望 xcodebuild 的日志通过管道传输到 stdout AND php -r "$code"

xcodebuild -scheme "<myscheme>" archive | tee >(php -r "$code" --)

这也有效,构建日志显示,如果我将 php -r "$code" -- 更改为 php -r "$code" -- | cat,它会记录 .dSYM 文件位置。

但是,以下内容不起作用:

xcodebuild -scheme "<myscheme>" archive | tee >(dsym=$(php -r "$code" --))

#this one is the closest but is the wrong way around,
#dsym = all the output, the filename is sent to stdout
exec 5>&1
dsym=$(xcodebuild -scheme "<myscheme>" archive | tee >(php -r "$code" >&5))

而且我无法理解 read -u X dsym 的工作原理或工作原理。有谁知道我会怎么做:


测试: 保存文件 scheme.out 并将 xcodebuild... 替换为 cat scheme.out

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nibh
nulla, tempor nec dolor ac, eleifend imperdiet diam. Mauris tristique
congue condimentum. Nullam commodo erat fringilla vestibulum tempus.
Aenean mattis varius erat in venenatis. Donec eu tellus urna. Morbi
lacinia vulputate purus, eu egestas tortor varius eget. Curabitur
vitae commodo elit, vitae ullamcorper leo.
Touch some_test_dsym_file.dSYM
Nunc malesuada, nisi at ultricies lobortis, odio diam rhoncus urna,
sed scelerisque enim ipsum eget quam. Nunc ut iaculis sem. Pellentesque
massa odio, sodales nec lacinia nec, rutrum eu neque. Aenean quis neque
magna. Nam quis dictum quam. Proin ut libero tortor. Class aptent taciti
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
Vivamus vehicula fringilla consequat. Curabitur tincidunt est sed magna
congue tristique. Maecenas aliquam nibh eget pellentesque pellentesque.
Quisque gravida cursus neque sed interdum. Proin ornare dapibus
dignissim.

期望输出

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nibh
nulla, tempor nec dolor ac, eleifend imperdiet diam. Mauris tristique
congue condimentum. Nullam commodo erat fringilla vestibulum tempus.
Aenean mattis varius erat in venenatis. Donec eu tellus urna. Morbi
lacinia vulputate purus, eu egestas tortor varius eget. Curabitur
vitae commodo elit, vitae ullamcorper leo.
Touch some_test_dsym_file.dSYM
Nunc malesuada, nisi at ultricies lobortis, odio diam rhoncus urna,
sed scelerisque enim ipsum eget quam. Nunc ut iaculis sem. Pellentesque
massa odio, sodales nec lacinia nec, rutrum eu neque. Aenean quis neque
magna. Nam quis dictum quam. Proin ut libero tortor. Class aptent taciti
sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
Vivamus vehicula fringilla consequat. Curabitur tincidunt est sed magna
congue tristique. Maecenas aliquam nibh eget pellentesque pellentesque.
Quisque gravida cursus neque sed interdum. Proin ornare dapibus
dignissim.

echo $dsym

的期望输出
some_test_dsym_file.dSYM

您的代码有很多依赖项。我将在不使用标准 unix 工具之外的任何东西的情况下说明我认为您需要的内容。

这会运行一个命令,seq 4,并将其所有输出发送到标准输出,并将其所有输出发送到另一个命令,sed 's/3/3-processed/',其输出被捕获在一个变量中, var:

$ exec 3>&1
$ var=$(seq 4 | tee >(cat >&3) | sed 's/3/3-processed/')
1
2
3
4

为了说明我们成功捕获了sed命令的输出:

$ echo "$var"
1
2
3-processed
4

解释: var=$(...) 捕获文件句柄 1 (stdout) 的输出并将其分配给 var。因此,为了使输出也出现在 stdout 上,我们需要将 stdout 复制到另一个文件句柄 before $(...) 重定向它。因此,我们使用 exec 将标准输出复制为文件句柄 3。这样,tee >(cat >&3) 将命令的输出发送到原始标准输出(现在称为 3)和文件句柄 1 传递到管道的下一阶段。

因此,使用您的工具链,尝试:

exec 5>&1
dsym=$(xcodebuild -scheme "<myscheme>" archive | tee >(cat >&5) | php -r "$code")