बैश हेरेडोक के अंदर चर का उपयोग करना


192

मैं एक बैश वंशानुगत के अंदर चरों को अलग करने की कोशिश कर रहा हूँ:

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

काम नहीं करता है, क्योंकि >outfileवर्तमान शेल में फ़ाइल को खोलता है, जो sudo का उपयोग नहीं कर रहा है।


9
यह एक समझने योग्य भ्रम है! जैसा कि नीचे उल्लेख किया गया है, सीमांकक के किसी भी भाग को उद्धृत करने से हेरेडोक में विस्तार बंद हो जाता है (जैसे कि यह अंदर था ''), लेकिन उद्धृत नहीं करते हुए सीमांकक विस्तार का विस्तार करता है (जैसे कि यह अंदर था "")। हालांकि, पर्ल में आपका अंतर्ज्ञान सही है, जहां एकल-उद्धृत पहचानकर्ता के साथ एक वंशानुगत व्यवहार करता है जैसे कि यह एकल उद्धरणों में थे, एक दोहरे-उद्धरण वाले पहचानकर्ता के साथ जैसे कि दोहरे उद्धरण चिह्नों में, और एक बैक-टिक वाले पहचान पत्र के साथ यदि ! देखें: perlop: << EOF
Nils von Barth

जवाबों:


252

आपके पहले प्रश्न के उत्तर में, कोई पैरामीटर प्रतिस्थापन नहीं है क्योंकि आपने उद्धरणों में सीमांकक डाल दिया है - बैश मैनुअल कहता है :

यहाँ दस्तावेजों का प्रारूप है:

      <<[-]word
              here-document
      delimiter

कोई पैरामीटर विस्तार, कमांड प्रतिस्थापन, अंकगणितीय विस्तार या pathname विस्तार शब्द पर नहीं किया जाता है । यदि शब्द के किसी भी अक्षर को उद्धृत किया जाता है, तो सीमांकक शब्द पर उद्धरण हटाने का परिणाम है, और यहां दस्तावेज़ में लाइनों का विस्तार नहीं किया गया है। यदि शब्द अयोग्य है, तो यहां दस्तावेज़ की सभी पंक्तियों को पैरामीटर विस्तार, कमांड प्रतिस्थापन और अंकगणितीय विस्तार के अधीन किया गया है। [...]

यदि आप अपने पहले उदाहरण को बदलने के <<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
वॉल्टेयर

कृपया मुझे बताएं कि बैश में दफन एक अच्छा कारण है कि ऐसा क्यों है।
लैंडन कुह्न

96

इसके साथ उद्धरणों का उपयोग न करें <<EOF:

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

परिवर्तनीय विस्तार यहाँ-डॉक्स के अंदर डिफ़ॉल्ट व्यवहार है। आप लेबल को उद्धृत करके उस व्यवहार को अक्षम करते हैं (एकल या दोहरे उद्धरण के साथ)।


36

पहले के जवाबों के लिए देर से कोरोलॉरी के रूप में, आप शायद उन स्थितियों में समाप्त हो जाते हैं, जहां आप कुछ नहीं बल्कि सभी चर को अलग करना चाहते हैं । आप डॉलर के संकेतों और बैकटिक्स से बचने के लिए बैकस्लैश का उपयोग करके इसे हल कर सकते हैं; या आप स्थिर पाठ को एक चर में रख सकते हैं।

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.