如何在链接命令时使用最后执行命令中多个命令的输出?

如何在链接命令时使用最后执行命令中多个命令的输出?

我有两个命令,如下:

这给出了存储库名称:

az acr repository list -n registry -o tsv 

输出看起来像:

name1
name2
...

这给出了一个存储库的摘要代码:

az acr manifest list-metadata -r ${REGISTRY} --name ${REPO} --query "[?tags[0]==null].digest" -o tsv

输出看起来像:

digest1
digest2
...

我想输出存储库名称和摘要代码。

尝试过:

az acr repository list -n registry -o tsv \ 
| xargs -I% az acr manifest list-metadata -r ${REGISTRY} --n % --query "[?tags[0]==null].digest" -o tsv \
| xargs -I% echo "%: %" 

实际输出:

digest_code: digest_code

预期输出:

repo_name: digestcode

答案1

你需要类似的东西:

export REPO
az acr repository list -n registry -o tsv |
  while IFS= read -r REPO; do
    az acr manifest list-metadata -r "$REGISTRY" --n "$REPO" --query '[?tags[0]==null].digest' -o tsv |
      awk '{print ENVIRON["REPO"]": "$0}'
  done

调用awk以相应的存储库名称为每个清单命令的输出添加前缀。

或者,如果您需要在每个存储库/摘要对上运行其他命令:

az acr repository list -n registry -o tsv |
  while IFS= read -r repo; do
    az acr manifest list-metadata -r "$REGISTRY" --n "$repo" --query '[?tags[0]==null].digest' -o tsv |
      while IFS= read -r digest; do
        other-cmd --repo "$repo" --digest "$digest"
      done
  done

使用zsh,您还可以执行以下操作:

for repo ( ${(f)"$(az acr repository list -n registry -o tsv)"} ) {
  digests=( ${(f)"$(az acr manifest list-metadata -r $REGISTRY --n $repo --query '[?tags[0]==null].digest' -o tsv)"})
  print -rC1 -- $repo': '$^digests
}
for repo ( ${(f)"$(az acr repository list -n registry -o tsv)"} )
  for digest ( ${(f)"$(az acr manifest list-metadata -r $REGISTRY --n $repo --query '[?tags[0]==null].digest' -o tsv)"})
    other-cmd --repo $repo --digest $digest

在 a 中Makefile,看起来像:

target:
    az acr repository list -n registry -o tsv | \
      while IFS= read -r repo; do \
        az acr manifest list-metadata -r "$$REGISTRY" --n "$$repo" --query '[?tags[0]==null].digest' -o tsv | \
          while IFS= read -r digest; do \
            other-cmd --repo "$$repo" --digest "$$digest"; \
          done; \
      done

虽然它位于 Makefile 中的几行中,但这些行被连接在一起,\删除了尾部 s,并且在将结果传递给 之前$$将 s 更改为s ,因此需要添加几个s 来在内联 shell 脚本中分隔命令。$sh -c;

您可能希望将代码放入脚本中以使其更清晰。

答案2

猜测,通过对您尝试的解决方案和您想要的其他答案进行逆向工程n₁ + n2 + …输出行,例如

blue: sky
blue: berry
blue: jay
red: stop sign
red: cardinal
red: tomato
red: fire
green: grass
green: beans

斯特凡·查泽拉斯的回答很好,特别是当您不知道存储库名称中可能包含哪些字符时。但是,它不适用于非常旧版本的 Awk。

这个非常相似的答案使用 sed 而不是 Awk。 sed 的资源密集程度较低,并且运行速度可能更快。

az acr repository list -n registry -o tsv |
  while IFS= read -r REPO; do
    az acr manifest list-metadata -r "$REGISTRY" --name "$REPO" \
                    --query "[?tags[0]==null].digest" -o tsv |
        sed "s/^/$REPO: /"
  done

export不需要)这应该与 Stéphane 的答案相同,除非存储库名称可能包含/或 &。是 /一个常用但任意的分隔符。如果您确定存储库名称不包含 &或 , 那么您可以通过将命令更改为来|使其更安全sed

        sed "s|^|$REPO: |"

如果存储库名称可能包含 &,则处理起来会有些困难。

请注意,如果任何存储库名称或摘要代码可能包含.

如果存储库名称或摘要代码都不包含空格,您可以通过将输出通过管道传输到column -t.


顺便看看${variable_name} 并不意味着你认为它的作用......

相关内容