बैश कंटीन्यू लाइन्स


158

आप बैश निरंतरता लाइनों का उपयोग कैसे करते हैं?

मुझे एहसास है कि आप ऐसा कर सकते हैं:

echo "continuation \
lines"
>continuation lines

हालाँकि, यदि आपके पास इंडेंट कोड है, तो यह इतनी अच्छी तरह से काम नहीं करता है:

    echo "continuation \
    lines"
>continuation     lines

5
Google का बैश शैल स्टाइल गाइड "यहाँ" के लिए "यदि आपको ऐसे तार लिखने हैं जो 80 वर्णों से अधिक लंबे हों" के लिए दस्तावेज़ों की अनुशंसा करता है । देखिए @ tripleee का जवाब
ट्रेवर बॉयड स्मिथ

google.github.io/styleguide/… - यह नए दस्तावेज़ में सीधा लिंक है
jcollum

जवाबों:


161

यह वही हो सकता है जो आप चाहते हैं

$       echo "continuation"\
>       "lines"
continuation lines

यदि यह प्रतिध्वनित करने के लिए दो तर्क बनाता है और आप केवल एक चाहते हैं, तो आइए स्ट्रिंग संकेतन देखें। बैश में, दो तारों को एक दूसरे के बगल में रखकर:

$ echo "continuation""lines"
continuationlines

तो एक इंडेंट के बिना एक निरंतरता लाइन एक स्ट्रिंग को तोड़ने का एक तरीका है:

$ echo "continuation"\
> "lines"
continuationlines

लेकिन जब एक इंडेंट का उपयोग किया जाता है:

$       echo "continuation"\
>       "lines"
continuation lines

आपको दो तर्क मिलते हैं क्योंकि यह अब सहमति नहीं है।

यदि आप एक ऐसी स्ट्रिंग चाहते हैं, जो इंडेंट करते समय लाइनों को पार करती हो, लेकिन उन सभी रिक्त स्थान को प्राप्त नहीं कर रही हो, तो एक दृष्टिकोण जिसे आप आज़मा सकते हैं वह है निरंतरता रेखा को खोदकर और चर का उपयोग करना:

$ a="continuation"
$ b="lines"
$ echo $a$b
continuationlines

यह आपको अतिरिक्त चर की कीमत पर साफ-सुथरा इंडेंटेड कोड रखने की अनुमति देगा। यदि आप चर को स्थानीय बनाते हैं तो यह बहुत बुरा नहीं होना चाहिए।


1
आपकी मदद के लिए धन्यवाद, लेकिन जब यह रिक्त स्थान को हटा देता है, तो वे अब अलग पैरामीटर हैं (बैश दूसरी पंक्ति पर रिक्त स्थान को एक पैरामीटर विभाजक के रूप में व्याख्या कर रहे हैं) और अब केवल इको कमांड के कारण सही ढंग से मुद्रित हैं।

1
ओह, आप लाइनों को स्पैन करने के लिए सिंगल (बैश) स्ट्रिंग चाहेंगे! मुझे अब दिख गया।
बजे रे तोल

4
एक चर के साथ समाधान:s="string no. 1" s+="string no. 2" s+=" string no. 3" echo "$s"
जॉनी थंडरमैन 15'16

30

यहां <<-HEREटर्मिनेटर के साथ दस्तावेज़ इंडेंटेड मल्टी-लाइन टेक्स्ट स्ट्रिंग्स के लिए अच्छी तरह से काम करते हैं। यह यहां से किसी भी प्रमुख टैब को यहां से हटा देगा। (लाइन टर्मिनेटर अभी भी रहेंगे, हालांकि)

cat <<-____HERE
    continuation
    lines
____HERE

Http://ss64.com/bash/syntax-here.html भी देखें

यदि आपको कुछ संरक्षित करने की आवश्यकता है, लेकिन सभी नहीं, तो प्रमुख व्हाट्सएप, आप कुछ का उपयोग कर सकते हैं

sed 's/^  //' <<____HERE
    This has four leading spaces.
    Two of them will be removed by sed.
____HERE

या शायद नए trसिरे से छुटकारा पाने के लिए उपयोग करें:

tr -d '\012' <<-____
    continuation
     lines
____

(दूसरी पंक्ति में एक टैब और एक स्पेस अप फ्रंट है; टैब को हेरेडोक टर्मिनेटर से पहले डैश ऑपरेटर द्वारा हटा दिया जाएगा, जबकि स्पेस संरक्षित रहेगा।)

कई लाइनों पर लंबे जटिल तारों को लपेटने के लिए, मुझे पसंद है printf:

printf '%s' \
    "This will all be printed on a " \
    "single line (because the format string " \
    "doesn't specify any newline)"

यह उन संदर्भों में भी अच्छी तरह से काम करता है जहां आप शेल स्क्रिप्ट के अनौपचारिक टुकड़ों को किसी अन्य भाषा में एम्बेड करना चाहते हैं जहां होस्ट भाषा का सिंटैक्स आपको यहां दस्तावेज़ का उपयोग करने की अनुमति नहीं देगा, जैसे कि Makefileया Dockerfile

printf '%s\n' >./myscript \
    '#!/bin/sh` \
    "echo \"G'day, World\"" \
    'date +%F\ %T' && \
chmod a+x ./myscript && \
./myscript

मेरे लिए काम नहीं करता है। उबंटू 16.04। मैं उम्मीद की एक पंक्ति के बजाय दो लाइनें प्राप्त करता हूं।
पेंघ गेंग

@PengheGeng वास्तव में, यह इंडेंटेशन से छुटकारा पाने की समस्या को हल करता है, न कि एक साथ मिलाने वाली लाइनों से। आप अभी भी एक पंक्ति के अंत में दो रेखाओं को एक साथ जोड़ने के लिए नई पंक्ति को बैकस्लैश कर सकते हैं।
ट्रिपल जूल 20'18

(लेकिन printfअब इसका पहला उदाहरण भी देखें ।)
ट्रिपल ३

12

आप बैश सरणियों का उपयोग कर सकते हैं

$ str_array=("continuation"
             "lines")

फिर

$ echo "${str_array[*]}"
continuation lines

एक अतिरिक्त स्थान है, क्योंकि (बैश मैनुअल के बाद):

यदि शब्द डबल-उद्धृत है, ${name[*]}तो IFS चर के पहले वर्ण द्वारा अलग किए गए प्रत्येक सरणी सदस्य के मान के साथ एक शब्द का विस्तार करता है

तो IFS=''अतिरिक्त जगह से छुटकारा पाने के लिए सेट करें

$ IFS=''
$ echo "${str_array[*]}"
continuationlines

4

कुछ परिदृश्यों में, बैश के संगति क्षमता का उपयोग करना उचित हो सकता है।

उदाहरण:

temp='this string is very long '
temp+='so I will separate it onto multiple lines'
echo $temp
this string is very long so I will separate it onto multiple lines

बैश मैन पेज के PARAMETERS अनुभाग से:

नाम = [value] ...

... उस संदर्भ में जहां एक असाइनमेंट स्टेटमेंट शेल वैरिएबल या एरे इंडेक्स के लिए मान प्रदान कर रहा है, + = ऑपरेटर का उपयोग वेरिएबल के पिछले मूल्य को जोड़ने या जोड़ने के लिए किया जा सकता है। जब + = एक चर पर लागू किया जाता है जिसके लिए पूर्णांक विशेषता निर्धारित की गई है, तो मान को अंकगणितीय अभिव्यक्ति के रूप में मूल्यांकन किया जाता है और चर के वर्तमान मूल्य में जोड़ा जाता है, जिसका मूल्यांकन भी किया जाता है। जब + = यौगिक असाइनमेंट का उपयोग करके एक सरणी चर पर लागू होता है (नीचे दिए गए एरर्स देखें), चर का मान परेशान नहीं है (जैसा कि यह = उपयोग करते समय) है, और नए मान सरणी के अधिकतम इंडेक्स की तुलना में अधिक से अधिक एक शुरुआत में जोड़ दिए गए हैं। (अनुक्रमित सरणियों के लिए) या एक सहयोगी सरणी में अतिरिक्त कुंजी-मूल्य जोड़े के रूप में जोड़ा गया। जब एक स्ट्रिंग-वैल्यू वैरिएबल पर लागू किया जाता है, तो वैल्यू का विस्तार किया जाता है और वेरिएबल के वैल्यू में जोड़ा जाता है।


शायद इस पृष्ठ पर सबसे अच्छी सलाह। HEREDOC का उपयोग करना और <CR> s के लिए अनुवाद में पाइप करना सुपर अनइंस्टिट्यूट है और तब विफल होता है जब स्ट्रिंग को वास्तव में अलग से लाइन सेपरेटर रखने की आवश्यकता होती है।
शाम

2

मैं एक ऐसी स्थिति में आया था जिसमें मुझे कमांड तर्क के भाग के रूप में एक लंबा संदेश भेजना था और लाइन की लंबाई सीमा का पालन करना था। आदेश कुछ इस तरह दिखते हैं:

somecommand --message="I am a long message" args

जिस तरह से मैंने इसे हल किया है वह एक दस्तावेज़ के रूप में संदेश को स्थानांतरित करने के लिए है (जैसे @tripleee ने सुझाव दिया)। लेकिन यहां एक दस्तावेज एक स्टडिन बन जाता है, इसलिए इसे वापस पढ़ने की आवश्यकता है, मैं नीचे दिए गए दृष्टिकोण के साथ गया:

message=$(
    tr "\n" " " <<- END
        This is a
        long message
END
)
somecommand --message="$message" args

इसका फायदा यह है कि $messageइसका उपयोग बिना किसी अतिरिक्त व्हाट्सएप या लाइन ब्रेक के लगातार तार के रूप में किया जा सकता है।

ध्यान दें कि ऊपर दी गई वास्तविक संदेश लाइनें tabप्रत्येक वर्ण के साथ उपसर्ग कर रही हैं , जो कि यहां स्वयं दस्तावेज़ द्वारा छीन ली गई है (उपयोग के कारण <<-)। अभी भी अंत में लाइन ब्रेक हैं, जो तब ddरिक्त स्थान के साथ बदल दिए जाते हैं।

यह भी ध्यान दें कि यदि आप नई कड़ियों को नहीं हटाते हैं, तो वे दिखाई देंगे जैसे "$message"कि विस्तार किया गया है। कुछ मामलों में, आप दोहरे उद्धरण चिह्नों को हटाकर वर्कअराउंड करने में सक्षम हो सकते हैं $message, लेकिन संदेश अब एक भी तर्क नहीं होगा।


2

वाक्यविन्यास के चतुर उपयोग के माध्यम से भी लाइन निरंतरता प्राप्त की जा सकती है।

के मामले में echo:

# echo '-n' flag prevents trailing <CR> 
echo -n "This is my one-line statement" ;
echo -n " that I would like to make."
This is my one-line statement that I would like to make.

Var के मामले में:

outp="This is my one-line statement" ; 
outp+=" that I would like to make." ; 
echo -n "${outp}"
This is my one-line statement that I would like to make.

Var के मामले में एक और दृष्टिकोण:

outp="This is my one-line statement" ; 
outp="${outp} that I would like to make." ; 
echo -n "${outp}"
This is my one-line statement that I would like to make.

देखा!


1

आप केवल नई लाइनों के साथ इसे अलग कर सकते हैं (बैकस्लैश का उपयोग किए बिना) इंडेंटेशन के भीतर निम्नानुसार और नई लाइनों की सिर्फ पट्टी।

उदाहरण:

echo "continuation
of 
lines" | tr '\n' ' '

या अगर यह एक वैरिएबल डेफिनिशन है तो नईलाइन स्वचालित रूप से स्पेस में बदल जाती है। तो, लागू होने पर ही अतिरिक्त स्थानों की पट्टी।

x="continuation
of multiple
lines"
y="red|blue|
green|yellow"

echo $x # This will do as the converted space actually is meaningful
echo $y | tr -d ' ' # Stripping of space may be preferable in this case

1

यह ठीक वैसा नहीं है जैसा कि उपयोगकर्ता ने पूछा है, लेकिन एक लंबी स्ट्रिंग बनाने का एक और तरीका है जो कई पंक्तियों को फैलाता है, यह वृद्धिशील रूप से इसका निर्माण करता है, जैसे:

$ greeting="Hello"
$ greeting="$greeting, World"
$ echo $greeting
Hello, World

जाहिर है इस मामले में इसे एक बार बनाना आसान होगा, लेकिन लंबे स्ट्रिंग्स से निपटने पर यह स्टाइल बहुत हल्का और समझ में आ सकता है।


0

हालाँकि, यदि आपके पास इंडेंट कोड है, तो यह इतनी अच्छी तरह से काम नहीं करता है:

    echo "continuation \
    lines"
>continuation     lines

एकल उद्धरण के साथ प्रयास करें और तार को समाहित करें:

    echo 'continuation' \
    'lines'
>continuation lines

नोट: संघनन में एक व्हाट्सएप शामिल है।


2
यह इको और स्ट्रिंग तर्कों के साथ काम करता है, लेकिन यह अन्य चीजों के साथ काम नहीं करता है, जैसे कि चर असाइनमेंट। हालांकि सवाल चर के बारे में नहीं था, लेकिन प्रतिध्वनि का उपयोग केवल एक उदाहरण था। इसके बजाय echo अगर आपके पास था x=, तो आपको त्रुटि मिलेगी lines: command not found:।
एलएस

0

आप किस प्रकार के जोखिमों को स्वीकार करेंगे और डेटा को कितनी अच्छी तरह से जानते हैं और उस पर भरोसा करते हैं, इसके आधार पर, आप सरलीकृत परिवर्तनीय प्रक्षेप का उपयोग कर सकते हैं।

$: x="
    this
    is
       variably indented
    stuff
   "
$: echo "$x" # preserves the newlines and spacing

    this
    is
       variably indented
    stuff

$: echo $x # no quotes, stacks it "neatly" with minimal spacing
this is variably indented stuff

-2

यह संभवतः आपके प्रश्न का उत्तर नहीं देता है, लेकिन आप इसे वैसे भी उपयोगी पा सकते हैं।

पहली कमांड दूसरी स्क्रिप्ट द्वारा प्रदर्शित स्क्रिप्ट बनाती है।

तीसरी कमांड उस स्क्रिप्ट को निष्पादन योग्य बनाती है।

चौथा आदेश एक उपयोग उदाहरण प्रदान करता है।

john@malkovich:~/tmp/so$ echo $'#!/usr/bin/env python\nimport textwrap, sys\n\ndef bash_dedent(text):\n    """Dedent all but the first line in the passed `text`."""\n    try:\n        first, rest = text.split("\\n", 1)\n        return "\\n".join([first, textwrap.dedent(rest)])\n    except ValueError:\n        return text  # single-line string\n\nprint bash_dedent(sys.argv[1])'  > bash_dedent
john@malkovich:~/tmp/so$ cat bash_dedent 
#!/usr/bin/env python
import textwrap, sys

def bash_dedent(text):
    """Dedent all but the first line in the passed `text`."""
    try:
        first, rest = text.split("\n", 1)
        return "\n".join([first, textwrap.dedent(rest)])
    except ValueError:
        return text  # single-line string

print bash_dedent(sys.argv[1])
john@malkovich:~/tmp/so$ chmod a+x bash_dedent
john@malkovich:~/tmp/so$ echo "$(./bash_dedent "first line
>     second line
>     third line")"
first line
second line
third line

ध्यान दें कि यदि आप वास्तव में इस स्क्रिप्ट का उपयोग करना चाहते हैं, तो यह निष्पादन योग्य स्क्रिप्ट को स्थानांतरित करने के लिए अधिक समझ में आता है ~/binताकि यह आपके रास्ते में हो।

कैसे textwrap.dedentकाम करता है पर विवरण के लिए अजगर संदर्भ की जाँच करें ।

के उपयोग के हैं $'...'या "$(...)"वहाँ पहले से ही एक नहीं है कि अगर आप को भ्रमित कर रहा है, एक और सवाल (निर्माण प्रति एक) पूछते हैं। आपके द्वारा खोजे गए सवाल को लिंक प्रदान करना अच्छा हो सकता है, ताकि अन्य लोगों के पास एक जुड़ा हुआ संदर्भ हो।


6
सुविचारित- और संभवतः उपयोगी भी- हालाँकि यह हो सकता है, ओपी ने बेसिक बैश सिंटैक्स पर सलाह मांगी, और आपने उसे एक पायथन फ़ंक्शन परिभाषा दी, जिसमें OO प्रतिमान, असाधारण प्रवाह नियंत्रण और आयात का उपयोग किया गया है। इसके अलावा, आपने एक निष्पादन योग्य को एक स्ट्रिंग प्रक्षेप के भाग के रूप में कहा- ऐसा कुछ जो इस तरह का प्रश्न पूछने वाला व्यक्ति निश्चित रूप से अभी तक नहीं देखा होगा।
पार्थियन ने
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.