파이프 중간에 "여기 문서"를 어떻게 사용할 수 있나요?

파이프 중간에 "여기 문서"를 어떻게 사용할 수 있나요?

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 -

메모배쉬 참조 매뉴얼라고

파이프라인의 각 명령은 자체 하위 셸에서 실행됩니다.

따라서 첫 번째 솔루션에서도 파이프 없이 파이프를 구성할 때 ( )첫 번째 부분(이전 |)은 어쨌든 서브셸에서 실행됩니다. 두 번째 해결책은 이 서브셸을 명시적으로 만듭니다. 명시적을 사용한 후 (쉘은 명시적을 기다립니다 ). 이를 통해 종료 뒤에 무언가를 배치할 수 있습니다 EOF.

<<놀랍게도 첫 번째 솔루션을 사용하더라도 단일 복합 명령에서 둘 이상의 여기 문서( )를 사용할 수 있습니다 . 이러한 리디렉션은 파이프에서는 거의 의미가 없지만 &&및 에서는 유용할 수 있습니다 ||.

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 - <<…(세미콜론이 없음에 유의) 작동하지 않는다는 의미입니다.
  • 기술적으로 서브쉘에 없는 동일한 코드(예: 없이 ( ))도 작동하지만 변수는 메인 쉘에 남아 있습니다. 서브쉘에서 코드를 실행하면 변수가 함께 죽게 됩니다. 원본 코드에서는 변수가 기본 셸에 대해 설정되지 않았으므로 이것이 원하는 것이라고 생각합니다.

관련 정보