bash heredoc에서 변수 사용


192

bash heredoc 내부의 변수를 보간하려고합니다.

var=$1
sudo tee "/path/to/outfile" > /dev/null << "EOF"
Some text that contains my $var
EOF

예상대로 작동하지 않습니다 ( $var문자 그대로 처리되고 확장되지 않음).

sudo tee파일을 만들려면 sudo 가 필요하기 때문에 사용해야 합니다. 같은 일을 :

sudo cat > /path/to/outfile <<EOT
my text...
EOT

>outfilesudo를 사용하지 않는 현재 쉘에서 파일을 열기 때문에 작동 하지 않습니다.


9
이것은 이해할 수있는 혼란입니다! 아래에 언급 된 것처럼 구분 기호의 일부를 인용하면 heredoc에서 확장이 해제 ''되지만 (있는 것처럼) 구분 기호를 인용 하지 않으면 확장이 켜집니다 (에서처럼 ""). 그러나 Perl에서는 직관이 정확합니다. 작은 따옴표로 묶인 식별자가있는 heredoc은 작은 따옴표로 묶인 것처럼 동작합니다. 하나는 큰 따옴표로 묶은 식별자가 있고 다른 하나는 역 따옴표로 묶는 것처럼 따옴표가있는 것입니다. ! 참조 : perlop : << EOF
Nils von Barth

답변:


252

첫 번째 질문에 대한 답으로 구분 기호를 따옴표로 묶었으므로 매개 변수 대체가 없습니다 .bash 매뉴얼은 다음과 같이 말합니다 .

여기 문서의 형식은 다음과 같습니다.

      <<[-]word
              here-document
      delimiter

word 에서 매개 변수 확장, 명령 대체, 산술 확장 또는 경로 이름 확장이 수행되지 않습니다 . 단어의 문자 가 따옴표로 묶이면 구분 기호 는 단어에서 따옴표를 제거한 결과이며 여기 문서의 줄은 확장되지 않습니다. 단어 를 인용 부호로 묶지 않으면 여기 문서의 모든 줄에 매개 변수 확장, 명령 대체 및 산술 확장이 적용됩니다. [...]

<<EOF대신 사용하도록 첫 번째 예를 변경 << "EOF"하면 작동한다는 것을 알 수 있습니다.

두 번째 예에서 셸은 sudo매개 변수로만 호출 cat하며 리디렉션 sudo cat은 원래 사용자 의 출력에 적용됩니다 . 시도하면 작동합니다.

sudo sh -c "cat > /path/to/outfile" <<EOT
my text...
EOT

: 당신이 관심이 있다면 당신은 또한으로이 작업을 수행 할 수 (cat > /path/to/outfile) <<EOF의 자리에sudo sh -c ... <<EOF
볼테르

Bash에 묻힌 이유는 이것이 좋은 이유입니다.
Landon Kuhn

96

따옴표를 사용하지 마십시오 <<EOF:

var=$1
sudo tee "/path/to/outfile" > /dev/null <<EOF
Some text that contains my $var
EOF

변수 확장은 here-docs 내부의 기본 동작입니다. 레이블을 작은 따옴표 또는 큰 따옴표로 인용하여 해당 동작을 비활성화합니다.


36

여기에 이전 답변에 늦은 corolloary으로, 당신은 아마 당신이 원하는 상황에서 결국 일부 가 아닌 모든 변수가 보간 될 수 있습니다. 백 슬래시를 사용하여 달러 기호와 백틱을 피함으로써이 문제를 해결할 수 있습니다. 또는 정적 텍스트를 변수에 넣을 수 있습니다.

Name='Rich Ba$tard'
dough='$$$dollars$$$'
cat <<____HERE
$Name, you can win a lot of $dough this week!
Notice that \`backticks' need escaping if you want
literal text, not `pwd`, just like in variables like
\$HOME (current value: $HOME)
____HERE

데모 : https://ideone.com/rMF2XA

인용 메커니즘 중 \____HERE하나 "____HERE"또는 '____HERE'-또는는 모든 변수 보간을 비활성화하고 여기 문서를 리터럴 텍스트로 바꿉니다.

일반적인 작업은 로컬 변수를 스크립트와 결합하여 다른 쉘, 프로그래밍 언어 또는 원격 호스트에서 평가해야합니다.

local=$(uname)
ssh -t remote <<:
    echo "$local is the value from the host which ran the ssh command"
    # Prevent here doc from expanding locally; remote won't see backslash
    remote=\$(uname)
    # Same here
    echo "\$remote is the value from the host we ssh:ed to"
:

3
왜 이것이 투표에 실패했는지는 확실하지 않지만 , 현재 더 높은 투표 응답에 포함 되지 않은 유효한 메모를 추가합니다 .
Inian
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.