如何在管道中间使用“此处文档”?


1

我想使用heredoc作为模板生成一些内容:

passphrase=$(<passphrase) envsubst <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: openshift-passphrase
stringData:
  passphrase: ${passphrase}
EOF

把它管道oc create -f -

如果我在之后添加一个管道EOF,它就不起作用。

如何将具有可变替换的heredoc传输到消耗它的东西?


第一次EOF后不起作用?
保罗

@paulo要么EOF|不关闭多行,要么新EOF行完成工作和后续| 是在新命令的开始
simbo1905

Answers:


2

首先,您需要引用EOF刚才的任何部分<<。最自然的方式是<<"EOF",但是<<E"OF"甚至<<""EOF会做。如果没有这个,envsubst将获得${passphrase}已经扩展的字符串。由于envsubst对带有字符串$foo${foo}子字符串的字符串进行操作,因此事先扩展它们意味着envsubst无关。此外,在您的情况下,shell很可能会扩展${passphrase}为空字符串,因为代码中的变量定义只会影响envsubstshell本身; 除非预先在shell中设置具有相同名称的变量(意外?)。

现在我们来看你明确的问题。您可以将结果传递给您希望的任何命令,但仍需要将最终的EOF保持在单独的行中。一种方法是这样的:

passphrase=$(<passphrase) envsubst <<"EOF" | oc create -f -
apiVersion: v1
kind: Secret
metadata:
  name: openshift-passphrase
stringData:
  passphrase: ${passphrase}
EOF

或者您可以在子shell中运行您拥有的代码:

( passphrase=$(<passphrase) envsubst <<"EOF"
apiVersion: v1
kind: Secret
metadata:
  name: openshift-passphrase
stringData:
  passphrase: ${passphrase}
EOF
) | oc create -f -

注意Bash参考手册

管道中的每个命令都在其自己的子shell中执行

因此,即使在第一个解决方案中,当我们设法构建我们的管道时( ),它的第一部分(之前|)仍然在子壳中运行。第二个解决方案使这个子shell明确。在我们使用explicit之后(,shell等待显式)。这允许我们在终止后放置一些东西EOF

令人惊讶的是,即使使用第一个解决方案,您也可以<<在单个复合命令中使用多个here document()。这种重定向在管道中没什么意义,但它们可能对&&和有用||

command1 <<EOF && command2 <<EOF || command3 <<EOF
content1
EOF
content2
EOF
content3
EOF

同样的重新排列,明确的子壳:

( command1 <<EOF
content1
EOF
) && ( command2 <<EOF
content2
EOF
) || command3 <<EOF
content3
EOF

根据情况,您可能更喜欢一种符号而不是另一种符号。

回到你的具体例子。使用子shell,您甚至不需要envsubst

( passphrase=$(<passphrase); oc create -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: openshift-passphrase
stringData:
  passphrase: ${passphrase}
EOF
)

这种方式与前两种方式之间存在一些有趣的差异:

  • 这次子壳本身应该扩展${passphrase},因此<<EOF,不是<<"EOF"
  • 为此,变量必须为子shell所知,而不仅仅是oc; 这意味着… passphrase=$(<passphrase) oc create -f - <<…(注意缺少分号)是行不通的。
  • 从技术上讲,不在子shell中(即没有( ))的相同代码也可以工作,但是变量将保留在主shell中。在子shell中运行代码会使变量死掉。在原始代码中,没有为主shell设置变量,所以我想这就是你想要的。

感谢非常全面的答案。我希望我能为每个部分投票一次。
simbo1905
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.