अतिरिक्त स्थान के साथ मल्टी-लाइन स्ट्रिंग (संरक्षित इंडेंटेशन)


409

मैं निम्नलिखित के साथ एक फ़ाइल में कुछ पूर्व-परिभाषित ग्रंथ लिखना चाहता हूं:

text="this is line one\n
this is line two\n
this is line three"

echo -e $text > filename

मैं कुछ इस तरह की उम्मीद कर रहा हूँ:

this is line one
this is line two
this is line three

लेकिन यह मिला:

this is line one
 this is line two
 this is line three

मैं सकारात्मक हूं कि प्रत्येक के बाद कोई स्थान नहीं है \n, लेकिन अतिरिक्त स्थान कैसे निकलता है?


2
मुझे यकीन नहीं है लेकिन .. अगर आप सिर्फ text="this is line one\nthis is line two\nthis is line three"एक ही लाइन में टाइप करते हैं तो कैसे ..? (बिना किसी प्रवेश के)
योहनस खोसियावन '29

4
\nप्रत्येक लाइन पर निकालें , आप पहले से ही नई लाइन पर जाने के लिए नई लाइन मार चुके हैं
मार्क सेटेल

आपने पहले ही दे दिया है। \nतो आप नई लाइन में अगली पंक्ति क्यों डालेंगे? बसtext="this is line one\nthis is line two\nthis is line three"
जयेश भोई

1
\nप्रत्येक पंक्ति के अंत में निकालने से सभी एकल लाइन पर आउटपुट एक साथ चलते हैं।
जोनाथन हार्टले

18
अहा: "$text"इको लाइन में डबल कोट्स डालना महत्वपूर्ण है। उनके बिना, न्यूलाइन्स (शाब्दिक और '\ n') दोनों में से कोई भी काम नहीं करता है। उनके साथ, वे सब करते हैं।
जोनाथन हार्टले

जवाबों:


662

हेरेडोक इस उद्देश्य के लिए अधिक सुविधाजनक लगता है। इसका उपयोग कई कमांड को एक्स या कैट जैसे कमांड दुभाषिया प्रोग्राम में भेजने के लिए किया जाता है

cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage

इसके बाद की स्ट्रिंग <<इंगित करती है कि कहां रुकना है।

इन पंक्तियों को फ़ाइल में भेजने के लिए, उपयोग करें:

cat > $FILE <<- EOM
Line 1.
Line 2.
EOM

आप इन लाइनों को एक चर में संग्रहीत कर सकते हैं:

read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM

यह लाइनों को नामित चर पर संग्रहीत करता है VAR

प्रिंट करते समय, चर के चारों ओर के उद्धरण याद रखें, अन्यथा आपको न्यूलाइन वर्ण दिखाई नहीं देंगे।

echo "$VAR"

इससे भी बेहतर, आप इंडेंटेशन का उपयोग करके इसे अपने कोड में अधिक बाहर खड़ा कर सकते हैं। इस बार टैब को प्रदर्शित होने से रोकने के लिए बस एक के -बाद एक जोड़ें <<

read -r -d '' VAR <<- EOM
    This is line 1.
    This is line 2.
    Line 3.
EOM

लेकिन तब आपको अपने कोड में इंडेंटेशन के लिए टैब का इस्तेमाल करना चाहिए, स्पेस का नहीं।


38
आपके पास << - 2 और 5 वें कोड ब्लॉक की पहली पंक्ति पर << के बजाय क्यों है? करता है - कुछ खास करना?
लाहफू

35
@ sup3rman '-' प्रमुख टैब को अनदेखा करता है। देखें stackoverflow.com/questions/2500436/…
kervin

7
मैं स्टेटस 0 के साथ रीड एक्जिट कैसे बना सकता हूं? ऐसा लगता है कि यह लाइन के अंत का पता नहीं लगा सकता (क्योंकि यह -d '' है) और 1 से बाहर निकलता है जो स्क्रिप्ट में होने पर आपकी मदद नहीं करता है।
मिशा स्लीसरेव

6
@MisSlyusarev उपयोग -d '\ 0' और अपनी अंतिम पंक्ति के अंत में एक \ 0 जोड़ें
लार्स श्नाइडर

11
मेरे लिए काम नहीं किया -dविकल्प का उपयोग करना read -r -d '' VARIABLE <<- EOM
dron22

186

यदि आप स्ट्रिंग को एक चर में लाने की कोशिश कर रहे हैं, तो एक और आसान तरीका कुछ इस तरह है:

USAGE=$(cat <<-END
    This is line one.
    This is line two.
    This is line three.
END
)

यदि आप टैब (यानी, 't') के साथ अपने स्ट्रिंग को इंडेंट करते हैं, तो इंडेंटेशन छीन लिया जाएगा। यदि आप रिक्त स्थान के साथ इंडेंट करते हैं, तो इंडेंटेशन अंदर रह जाएगा।

नोट: यह है कि पिछले समापन कोष्ठक एक और लाइन पर है महत्वपूर्ण। ENDपाठ अपने आप में एक लाइन पर दिखाई देना चाहिए।


1
क्या यह महत्वपूर्ण है? )उसी लाइन पर मेरे मैक पर काम करता है । मुझे लगता है कि यह इसलिए है क्योंकि जो अपने बीच जाता है $(और )अपने ब्रह्मांड में निष्पादित करता है, और वास्तविक कमांड वैसे भी ')' नहीं देखेगा। मुझे आश्चर्य है कि अगर यह दूसरों के लिए भी काम करता है।
डेज

यह संभव है कि अलग-अलग गोले चीजों की अलग-अलग व्याख्या करेंगे। में बैश प्रलेखन यह कुछ भी कहने के लिए एक ही रास्ता या अन्य प्रतीत नहीं होता है, लेकिन सभी उदाहरण अपनी पंक्ति में पास है।
एंड्रयू मिनेर

मजेदार बात यह है, मैंने पाया कि जब आप USAGE वैरिएबल के लिए भी मूल्य निर्धारित करने का प्रयास कर रहे हैं, तो आपको जवाब मिल जाएगा। तो आपका जवाब बिल्कुल मेल खाता है। :)
बंक

1
POSIX कल्पना से @deej : यहाँ-दस्तावेज़ ... तब तक जारी है जब तक केवल सीमांकक और <newline> वाली पंक्ति नहीं है
Fornost

1
@ फॉर्नस्ट ने यह नहीं कहा कि मैंने क्या कहा
डेज

84

echoइसमें दिए गए तर्कों के बीच रिक्त स्थान जोड़ता है। $textचर विस्तार और शब्द विभाजन के अधीन है, इसलिए आपकी echoआज्ञा इसके बराबर है:

echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n"  ...

आप देख सकते हैं कि "यह" से पहले एक स्थान जोड़ा जाएगा। आप या तो newline वर्ण हटा सकते हैं, और $textnewlines को संरक्षित करने के लिए उद्धरण दे सकते हैं:

text="this is line one
this is line two
this is line three"

echo "$text" > filename

या आप उपयोग कर सकते हैं printf, जो अधिक मजबूत और पोर्टेबल है echo:

printf "%s\n" "this is line one" "this is line two" "this is line three" > filename

में bash, जो ब्रेस विस्तार का समर्थन करता है, तो आप भी कर सकता है:

printf "%s\n" "this is line "{one,two,three} > filename

1
यह समझाने के लिए धन्यवाद कि मॉड "इको" कमांड का उपयोग करते समय अतिरिक्त स्थान क्यों देखता है। बैश स्क्रिप्ट का उपयोग करते समय यह उत्तर भी अच्छी तरह से काम कर रहा है (जैसा कि इंटरैक्टिव शैल सत्र का विरोध करता है)। महसूस करें कि यह वास्तविक उत्तर है और एक स्वीकृत उत्तर होना चाहिए।
onelaview

1
इसका उत्तर स्वीकार किया जाना चाहिए। अन्य सभी उत्तरों ने ओपी के दर्द को हल करने के लिए कई अन्य दिलचस्प तरीके प्रदान किए , लेकिन तकनीकी रूप से यह सवाल था कि "अतिरिक्त स्थान कैसे निकलता है" और किसी ने भी इसे संबोधित नहीं किया :-) !!! धन्यवाद, जोश -1 रहस्य बनाने के लिए!
दिमित्री शेवकोप्लस

45

एक बाश स्क्रिप्ट में निम्नलिखित काम करता है:

#!/bin/sh

text="this is line one\nthis is line two\nthis is line three"
echo -e $text > filename

वैकल्पिक रूप से:

text="this is line one
this is line two
this is line three"
echo "$text" > filename

बिल्ली का नाम देता है:

this is line one
this is line two
this is line three

ऐसा लगता है कि शेल लिपियों के दौरान वैकल्पिक चाल काम करती है लेकिन यह बैश के लिए काम नहीं करती है।
मैकबुक

3
@ मैक विंडो मुझे लगता है कि के लिए -eविकल्प भूल गए हैं echo। कृपया पुन: प्रयास करें।
क्रिस मेव

41

मुझे और समाधान मिल गए हैं क्योंकि मैं चाहता था कि हर लाइन ठीक से इंडेंट हो:

  1. आप उपयोग कर सकते हैं echo:

    echo    "this is line one"   \
        "\n""this is line two"   \
        "\n""this is line three" \
        > filename

    यह काम नहीं करता है यदि आप एक पंक्ति के अंत में "\n"पहले डालते हैं \

  2. वैकल्पिक रूप से, आप printfबेहतर पोर्टेबिलिटी के लिए उपयोग कर सकते हैं (मुझे लगा कि बहुत सारी समस्याएं हैं echo):

    printf '%s\n' \
        "this is line one"   \
        "this is line two"   \
        "this is line three" \
        > filename
  3. अभी तक एक और समाधान हो सकता है:

    text=''
    text="${text}this is line one\n"
    text="${text}this is line two\n"
    text="${text}this is line three\n"
    printf "%b" "$text" > filename

    या

    text=''
    text+="this is line one\n"
    text+="this is line two\n"
    text+="this is line three\n"
    printf "%b" "$text" > filename
  4. मिश्रण से एक और समाधान प्राप्त किया जाता है printfऔर sed

    if something
    then
        printf '%s' '
        this is line one
        this is line two
        this is line three
        ' | sed '1d;$d;s/^    //g'
    fi

    आप कोड को इंडेंटेशन स्तर को हार्डकोड के रूप में इस तरह से स्वरूपित कोड को रिफलैक्ट करना आसान नहीं है।

  5. एक सहायक कार्य और कुछ चर प्रतिस्थापन चाल का उपयोग करना संभव है:

    unset text
    _() { text="${text}${text+
    }${*}"; }
    # That's an empty line which demonstrates the reasoning behind 
    # the usage of "+" instead of ":+" in the variable substitution 
    # above.
    _ ""
    _ "this is line one"
    _ "this is line two"
    _ "this is line three"
    unset -f _
    printf '%s' "$text"

जब कोड इंडेंटेशन और स्ट्रिंग इंडेंटेशन को स्वतंत्र रूप से संरक्षित करना चाहते हैं तो 3 बी मेरा पसंदीदा समाधान है, कम से कम जब मैं चर असाइनमेंट में 2 का उपयोग नहीं कर सकता हूं, और 3 ए की तुलना में अधिक पठनीय है। जब मुझे परवाह नहीं है तो मैं कई पंक्तियों पर उद्धृत उद्धरण को खुला रखता हूं।
16

बहुत अच्छा जवाब विशेष रूप से 3b
सुमित त्रेहान

"यह काम नहीं करता है यदि आप एक पंक्ति के अंत में \ n" "पहले ही डाल देते हैं।" - इको का उपयोग करते समय एक शानदार टिप है
नोआम मानोस

6

निम्नलिखित एक चर के लिए एक बहु-पंक्ति स्ट्रिंग असाइन करने का मेरा पसंदीदा तरीका है (मुझे लगता है कि यह अच्छा लग रहा है)।

read -r -d '' my_variable << \
_______________________________________________________________________________

String1
String2
String3
...
StringN
_______________________________________________________________________________

अंडरस्कोर की संख्या दोनों मामलों में समान (यहां 80) है।


0

बस एक सरल एक-पंक्ति के अवतरण का उल्लेख करना है क्योंकि यह कभी-कभी उपयोगी हो सकता है।

# for bash

v=" guga "$'\n'"   puga "

# Just for an example.
v2="bar "$'\n'"   foo "$'\n'"$v"

# Let's simplify the previous version of $v2.
n=$'\n'
v3="bar ${n}   foo ${n}$v"

echo "$v3" 

आपको ऐसा कुछ मिलेगा

बार 
   foo 
 Guga 
   पूगा 

सभी प्रमुख और समाप्त होने वाले सफेद स्थानों को सही संरक्षित किया जाएगा

echo "$v3" > filename

0

इसे करने के कई तरीके हैं। मेरे लिए, सीड में इंडेंटेड स्ट्रिंग को अच्छी तरह से काम करना।

printf_strip_indent() {
   printf "%s" "$1" | sed "s/^\s*//g" 
}

printf_strip_indent "this is line one
this is line two
this is line three" > "file.txt"

यह उत्तर माटुस्स पिओत्रोस्की के उत्तर पर आधारित था लेकिन थोड़ा परिष्कृत हुआ।


-1

यदि आप इसे नीचे रखते हैं तो यह काम करेगा:

AA='first line
\nsecond line 
\nthird line'
echo $AA
output:
first line
second line
third line
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.