Как использовать «здесь документ» в середине канала?

Как использовать «здесь документ» в середине канала?

Я хочу сгенерировать некоторый контент, используя heredoc в качестве шаблона:

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

и передать его по трубопроводу oc create -f -.

Если я добавлю вертикальную черту после EOF, это не сработает.

Как передать heredoc с заменой переменных в то, что его потребляет?

решение1

Сначала вам нужно заключить в кавычки любую часть EOFсразу после <<. Самый естественный способ — <<"EOF", но <<E"OF"или даже <<""EOFподойдет. Без этого envsubstполучите строку с ${passphrase}уже развернутой. Так как envsubstработает со строками с литералом $fooили ${foo}подстроками, предварительное их развертывание означает envsubstничего не делает. Кроме того, в вашем случае оболочка, скорее всего, расширится ${passphrase}до пустой строки, потому что определение переменной в вашем коде влияет только на envsubst, а не на саму оболочку; если только переменная с тем же именем (случайно?) не установлена ​​в оболочке заранее.

Теперь перейдем к вашему явному вопросу. Вы можете передать результат любой команде, но вам все равно нужно сохранить финальный EOF в отдельной строке. Один из способов сделать это так:

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

Или вы можете запустить код, который у вас есть, в подоболочке:

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

ПримечаниеСправочное руководство по Bashговорит

Каждая команда в конвейере выполняется в своей собственной подоболочке.

поэтому даже в первом решении, когда нам удалось построить наш канал без ( ), его первая часть (до |) в любом случае выполняется в подоболочке. Второе решение делает эту подоболочку explicit. После того, как мы используем explicit (, оболочка ждет explicit ). Это позволяет нам разместить что-то после завершающего EOF.

Удивительно, но даже с первым решением вы можете использовать более одного документа here ( <<) в одной составной команде. Такие перенаправления не имеют особого смысла в конвейере, но они могут быть полезны с &&и ||.

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

То же самое, переставленное, с явными подоболочками:

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

В зависимости от ситуации вы можете предпочесть одну нотацию другой.

Возвращаясь к вашему конкретному примеру. С подоболочкой вам даже не нужно envsubst:

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

Между этим способом и двумя предыдущими есть интересные различия:

  • На этот раз сама подоболочка должна расширяться ${passphrase}, следовательно <<EOF, нет <<"EOF".
  • Чтобы это работало, переменная должна быть известна подоболочке, а не только oc; это означает … passphrase=$(<passphrase) oc create -f - <<…(обратите внимание на отсутствие точки с запятой) что это не сработает.
  • Технически тот же код не в подоболочке (т.е. без ( )) также будет работать, но тогда переменная останется в основной оболочке. Запуск кода в подоболочке заставляет переменную умереть вместе с ним. В вашем исходном коде переменная не установлена ​​для основной оболочки, так что я думаю, это то, что вам нужно.

Связанный контент