Sử dụng các biến trong một bash heredoc


192

Tôi đang cố gắng nội suy các biến trong một bash heredoc:

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

Điều này không hoạt động như tôi mong đợi ( $varđược xử lý theo nghĩa đen, không được mở rộng).

Tôi cần sử dụng sudo teevì tạo tập tin yêu cầu sudo. Làm một cái gì đó như:

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

Không hoạt động, vì >outfilemở tệp trong trình bao hiện tại, không sử dụng sudo.


9
Đây là một sự nhầm lẫn dễ hiểu! Như đã lưu ý dưới đây, trích dẫn bất kỳ phần nào của dấu phân cách sẽ tắt mở rộng trong di truyền (như thể nó ở trong ''), nhưng không trích dẫn dấu phân cách bật mở rộng (như thể nó ở trong ""). Tuy nhiên, trực giác của bạn là chính xác trong Perl, trong đó một di sản với số nhận dạng trích dẫn đơn hoạt động như thể nó nằm trong dấu ngoặc đơn, một với số nhận dạng được trích dẫn kép như trong dấu ngoặc kép và một với số nhận dạng được đánh dấu ngược như thể trong dấu ngoặc kép ! Xem: perlop: << EOF
Nils von Barth

Câu trả lời:


252

Để trả lời cho câu hỏi đầu tiên của bạn, không có sự thay thế tham số nào vì bạn đã đặt dấu phân cách trong dấu ngoặc kép - hướng dẫn bash nói :

Định dạng của tài liệu ở đây là:

      <<[-]word
              here-document
      delimiter

Không có mở rộng tham số, thay thế lệnh, mở rộng số học hoặc mở rộng tên đường dẫn được thực hiện trên word . Nếu bất kỳ ký tự nào trong từ được trích dẫn, dấu phân cách là kết quả của việc loại bỏ trích dẫn trên từ và các dòng trong tài liệu ở đây không được mở rộng. Nếu từ không được trích dẫn, tất cả các dòng của tài liệu ở đây phải chịu sự mở rộng tham số, thay thế lệnh và mở rộng số học. [...]

Nếu bạn thay đổi ví dụ đầu tiên của bạn để sử dụng <<EOFthay vì << "EOF"bạn sẽ thấy rằng nó hoạt động.

Trong ví dụ thứ hai của bạn, shell sudochỉ gọi với tham số catvà chuyển hướng áp dụng cho đầu ra sudo catlà người dùng ban đầu. Nó sẽ hoạt động nếu bạn cố gắng:

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

Nếu bạn quan tâm, bạn cũng có thể làm điều này như: (cat > /path/to/outfile) <<EOFthay chosudo sh -c ... <<EOF
Voltaire

Xin vui lòng cho tôi biết chôn cất ở Bash là một lý do tốt tại sao điều này là như vậy.
Landon Kuhn

96

Đừng sử dụng dấu ngoặc kép với <<EOF:

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

Mở rộng biến là hành vi mặc định bên trong của tài liệu ở đây. Bạn vô hiệu hóa hành vi đó bằng cách trích dẫn nhãn (với dấu ngoặc đơn hoặc dấu ngoặc kép).


36

Là một câu trả lời muộn cho các câu trả lời trước đây ở đây, có lẽ bạn sẽ gặp phải tình huống bạn muốn một số nhưng không phải tất cả các biến được nội suy. Bạn có thể giải quyết điều đó bằng cách sử dụng dấu gạch chéo ngược để thoát các ký hiệu đô la và backticks; hoặc bạn có thể đặt văn bản tĩnh trong một biến.

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

Bản trình diễn: https://ideone.com/rMF2XA

Lưu ý rằng bất kỳ cơ chế trích dẫn nào - \____HEREhoặc "____HERE"hoặc '____HERE'- sẽ vô hiệu hóa tất cả phép nội suy biến đổi và biến tài liệu ở đây thành một đoạn văn bản bằng chữ.

Một tác vụ phổ biến là kết hợp các biến cục bộ với tập lệnh cần được đánh giá bởi trình bao, ngôn ngữ lập trình hoặc máy chủ từ xa khác.

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
Không chắc chắn tại sao điều này đã được bỏ phiếu xuống, nhưng nó thêm một ghi chú hợp lệ không được nêu trong câu trả lời được bình chọn cao hơn hiện nay.
Inian
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.