एक चर के लिए जटिल मल्टी-लाइन स्ट्रिंग लिखने का साफ तरीका


109

मुझे एक bash स्क्रिप्ट के अंदर एक वैरिएबल को कुछ जटिल xml लिखने की जरूरत है। एक्सएमएल को बैश स्क्रिप्ट के अंदर पढ़ने योग्य होना चाहिए क्योंकि यह वह जगह है जहां एक्सएमएल टुकड़ा लाइव होगा, इसे किसी अन्य फ़ाइल या स्रोत से नहीं पढ़ा जा रहा है।

तो मेरा सवाल यह है कि अगर मेरे पास एक लंबी स्ट्रिंग है जो मैं अपनी बैश स्क्रिप्ट के अंदर मानव पठनीय बनना चाहता हूं तो इसके लिए सबसे अच्छा तरीका क्या है?

आदर्श रूप से मुझे चाहिए:

  • किसी भी पात्र से बचने के लिए नहीं
  • यह कई लाइनों को तोड़ने के लिए यह मानव पठनीय है
  • यह इंडेंटेशन रखें

क्या यह ईओएफ या कुछ और के साथ किया जा सकता है, क्या कोई मुझे एक उदाहरण दे सकता है?

जैसे

String = <<EOF
 <?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
EOF

मैं शर्त लगाने को तैयार हूं कि आप उस डेटा को फिर से स्ट्रीम में डंप करने जा रहे हैं। जब आप चीजों को अधिक जटिल बना सकते हैं और धाराओं का उपयोग कर सकते हैं तो इसे एक चर में क्यों स्टोर करें?
ज़ेनेक्सर

जवाबों:


140

यह आपके पाठ को उद्धरण से बचने की आवश्यकता के बिना आपके चर में डाल देगा। यह असंतुलित उद्धरण (एपोस्ट्रोफिस, यानी ') भी संभाल लेगा । प्रहरी (ईओएफ) के आसपास उद्धरण डालकर पाठ को पैरामीटर विस्तार से गुजरने से रोकता है। इसके -d''कारण कई लाइनों को पढ़ना पड़ता है (नए सिरे से नजरअंदाज करना)। readएक बैश बिल्ट-इन है, इसलिए इसे बाहरी कमांड जैसे कॉल करने की आवश्यकता नहीं है cat

IFS='' read -r -d '' String <<"EOF"
<?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
EOF

17
बचने के लिए +1 cat
जेम्स स्नीनरिंग

4
catएक बाहरी कमांड है। इसका उपयोग नहीं करने से ऐसा करना बच जाता है। इसके अलावा, कुछ का यह भी मानना ​​है कि यदि आप बिल्ली का उपयोग दो से कम तर्कों के साथ कर रहे हैं तो "उर क्या गलत है" (जो "बेकार उपयोग" से अलग है cat)।
डेनिस विलियमसन

9
और कभी भी दूसरे
ईओएफ पर हस्ताक्षर न करें

9
मैंने उपर्युक्त कथन का उपयोग करने का प्रयास किया set -e। ऐसा लगता है कि readहमेशा गैर-शून्य रिटर्न देता है। आप कर सकते हैं मोटी का उपयोग करके इस व्यवहार! read -d .......
krissi

11
और अगर आप इस मल्टी-लाइन Stringवैरिएबल का उपयोग किसी फाइल में लिखने के लिए कर रहे हैं, तो वेरिएबल को "QUOTES" जैसे echo "${String}" > /tmp/multiline_file.txtया उसके आसपास रखें echo "${String}" | tee /tmp/multiline_file.txt। मुझे खोजने के लिए एक घंटे से अधिक समय लगा।
आदित्य

28

आप लगभग वहाँ रहे हैं। या तो आप अपनी स्ट्रिंग के असेंबली के लिए बिल्ली का उपयोग करते हैं या आप पूरे स्ट्रिंग को उद्धृत करते हैं (जिस स्थिति में आपको अपने स्ट्रिंग के अंदर के उद्धरण से बचना होगा):

#!/bin/sh
VAR1=$(cat <<EOF
<?xml version="1.0" encoding='UTF-8'?>
<painting>
  <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's "Foligno" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>
EOF
)

VAR2="<?xml version=\"1.0\" encoding='UTF-8'?>
<painting>
  <img src=\"madonna.jpg\" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's \"Foligno\" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>"

echo "${VAR1}"
echo "${VAR2}"

दुर्भाग्य से, "राफेल" में प्रेरित ने पहले काम नहीं किया।
डेनिस विलियमसन

दोनों असाइनमेंट मेरे लिए आखिरकार काम करते हैं। VAR1 में एकल उद्धरण एक समस्या नहीं होनी चाहिए (कम से कम बैश के लिए नहीं)। हो सकता है कि आपको सिंटैक्स हाइलाइटिंग द्वारा गुमराह किया गया हो?
जोशी

1
यह एक स्क्रिप्ट में काम करता है, लेकिन बैश प्रॉम्प्ट पर नहीं। स्पष्ट नहीं होने के लिए क्षमा करें।
डेनिस विलियमसन

1
ईओएफ को उद्धृत करना बेहतर है 'EOF'या "EOF", अन्यथा शेल चर को पार्स किया जाएगा।
स्टेनिस्लाव जर्मन-इवतुशेंको

13
#!/bin/sh

VAR1=`cat <<EOF
<?xml version="1.0" encoding='UTF-8'?>
<painting>
  <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
  <caption>This is Raphael's "Foligno" Madonna, painted in
  <date>1511</date>-<date>1512</date>.</caption>
</painting>
EOF
`
echo "VAR1: ${VAR1}"

यह बॉर्न शेल पर्यावरण के भीतर ठीक काम करना चाहिए


1
+1 यह समाधान $ {foo} जैसे परिवर्तनीय प्रतिस्थापन की अनुमति देता है
ऑफ्मो सेप

अपसाइड: श-संगत। डाउनसाइड: बैकट्स को बैश में डिप्रेस्ड / हतोत्साहित किया जाता है। अब अगर मुझे sh और bash के बीच चयन करना है ...
Zenexer

2
कब से बैकटिक्स को अपदस्थ / हतोत्साहित किया जाता है? सिर्फ जिज्ञासु
अलेक्जेंडर मिल्स

6

फिर भी ऐसा करने का एक और तरीका ...

मुझे स्क्रिप्ट इंडेंटेशन की अनुमति देने के लिए प्रत्येक पंक्ति के आरंभ में सारणीकरण<<- को छोड़ने वाले चर और विशेष का उपयोग करना पसंद है :

#!/bin/bash

mapfile Pattern <<-eof
        <?xml version="1.0" encoding='UTF-8'?>
        <painting>
          <img src="%s" alt='%s'/>
          <caption>%s, painted in
          <date>%s</date>-<date>%s</date>.</caption>
        </painting>
        eof

while IFS=";" read file alt caption start end ;do
    printf "${Pattern[*]}" "$file" "$alt" "$caption" "$start" "$end"
  done <<-eof
        madonna.jpg;Foligno Madonna, by Raphael;This is Raphael's "Foligno" Madonna;1511;1512
        eof

चेतावनी : केवल सारणीकरण से पहले कोई खाली जगह नहीं है ।eof

<?xml version="1.0" encoding='UTF-8'?>
 <painting>
   <img src="madonna.jpg" alt='Foligno Madonna, by Raphael'/>
   <caption>This is Raphael's "Foligno" Madonna, painted in
   <date>1511</date>-<date>1512</date>.</caption>
 </painting>
कुछ स्पष्टीकरण:
  • Mapfile एक सरणी में पूरे दस्तावेज़ यहाँ पढ़ें ।
  • वाक्य रचना "${Pattern[*]}"इस सरणी को एक स्ट्रिंग में डालती है।
  • मैं उपयोग करता हूं IFS=";"क्योंकि ;आवश्यक तारों में नहीं है
  • बाकी स्क्रिप्ट के लिए सिंटैक्स while IFS=";" read file ...को IFSसंशोधित करने से रोकते हैं । इसमें, केवल readसंशोधित का उपयोग करें IFS
  • कोई कांटा नहीं।

ध्यान दें कि mapfileबैश 4 या उच्चतर की आवश्यकता है। और वाक्यविन्यास उद्धरण में"${Pattern[*]}" सरणी को एक स्ट्रिंग में डाल देता है (जैसा कि उदाहरण कोड में दिखाया गया है)।
डेनिस विलियमसन

हां, बैश 4 बहुत नया था जब यह सवाल पूछा गया था।
एफ। होरी

2

अन्य कई उत्तरों में बहुत से कोने मामले हैं।

यह सुनिश्चित करने के लिए कि रिक्त स्थान, टैब, IFS आदि के साथ कोई समस्या नहीं है, एक बेहतर तरीका "हेरेडोक" निर्माण का उपयोग करना है, लेकिन uuencodeयहां बताए अनुसार उपयोग करने वाले हेरेडोक की सामग्री को एन्कोड करें:

https://stackoverflow.com/questions/6896025/#11379627

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