2015-11-19 10 views
18

व्यक्तिगत विकास और परियोजनाओं के लिए मैं काम करता हूं, हम टैब के बजाय चार रिक्त स्थान का उपयोग करते हैं। हालांकि, मुझे हेड्रोक का उपयोग करने की आवश्यकता है, और मैं इंडेशन प्रवाह को तोड़ने के बिना ऐसा नहीं कर सकता।रिक्त स्थान के साथ heredocs इंडेंटिंग

केवल काम कर रहे तरीका यह मैं के बारे में सोच सकते हैं करने के लिए इस होगा:

usage() { 
    cat << ' EOF' | sed -e 's/^ //'; 
    Hello, this is a cool program. 
    This should get unindented. 
    This code should stay indented: 
     something() { 
      echo It works, yo!; 
     } 
    That's all. 
    EOF 
} 

वहाँ यह करने के लिए एक बेहतर तरीका है?

मुझे बताएं कि यह Unix/Linux Stack Exchange पर है या नहीं।

+1

नहीं, यह एक प्रोग्रामिंग सवाल है, इसे यहाँ कानूनी है। जांच के लिए धन्यवाद। –

+0

यह ऐसा करने के लिए एक अच्छा, स्पष्ट, सीधा तरीका लगता है। ऑफहेड के अन्य तरीकों को नहीं जानते। जब मैं अधिक वोट प्राप्त करता हूं, तो मैं इसे उखाड़ दूंगा, शायद कोई दिलचस्प कुछ जानता है। –

+0

ओउ, अच्छा समाधान! दुर्भाग्यवश अधिकांश अन्य भाषाओं में संभव नहीं है, कोड के इंडेंटिंग ब्लॉक को मुश्किल बनाते हैं। – Kenney

उत्तर

21

(आप bash 4 का उपयोग कर रहे हैं, तो मैं क्या सोचता शुद्ध खोल और पठनीयता का सबसे अच्छा संयोजन है के लिए अंत करने के लिए स्क्रॉल करें।)

शेल स्क्रिप्ट के लिए, टैब का उपयोग कर वरीयता या शैली की बात नहीं है, इस तरह भाषा परिभाषित की जाती है।

usage() { 
    # Lines between EOF are each indented with the same number of tabs 
    # Spaces can follow the tabs for in-document indentation 
    cat <<-EOF 
     Hello, this is a cool program. 
     This should get unindented. 
     This code should stay indented: 
      something() { 
       echo It works, yo!; 
      } 
     That's all. 
    EOF 
} 

एक अन्य विकल्प अधिक उद्धरण और लाइन निरंतरता का उपयोग किए की कीमत पर पूरी तरह एक यहाँ दस्तावेज़ से बचने के लिए, यह है:

usage() { 
    printf '%s\n' \ 
     "Hello, this is a cool program." \ 
     "This should get unindented." \ 
     "This code should stay indented:" \ 
     " something() {" \ 
     "  echo It works, yo!" \ 
     " }" \ 
     "That's all." 
} 

आप POSIX अनुकूलता त्याग करने को तैयार हैं, तो आप एक का उपयोग कर सकते

usage() { 
    message=(
     "Hello, this is a cool program." 
     "This should get unindented." 
     "This code should stay indented:" 
     " something() {" 
     "  echo It works, yo!" 
     " }" 
     "That's all." 
    ) 
    printf '%s\n' "${message[@]}" 
} 

निम्नलिखित यहां docume का उपयोग करता है: सरणी स्पष्ट लाइन निरंतरता से बचने के लिए एनटी फिर से, लेकिन इस बार bash 4 के readarray आदेश के साथ एक सरणी पॉप्युलेट करने के लिए आदेश। पैरामीटर विस्तार प्रत्येक झूठ की शुरुआत से रिक्त स्थान की एक निश्चित संख्या को हटाने का ख्याल रखता है।

usage() { 
    # No tabs necessary! 
    readarray message <<' EOF' 
     Hello, this is a cool program. 
     This should get unindented. 
     This code should stay indented: 
      something() { 
       echo It works, yo!; 
      } 
     That's all. 
    EOF 
    # Each line is indented an extra 8 spaces, so strip them 
    printf '%s' "${message[@]#  }" 
} 

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

(इसके अलावा, (यह उपसर्ग पैटर्न के लिए एक मामूली परिवर्तन के साथ छोड़ा जा सकता है अंतरिक्ष निम्नलिखित बृहदान्त्र पठनीयता के लिए है।) जो व्हाइटस्पेस के साथ शुरू होता है यह है कि यह आपको यहां-डॉक के अंदर विस्तार करने से रोकता है। अगर आप ऐसा करना चाहते हैं, तो आपको या तो डिलीमीटर को अनइंडेंट छोड़ना होगा, या अपने नो-टैब नियम में एक मामूली अपवाद बनाना होगा और <<-EOF का उपयोग करना होगा और एक टैब इंडेंट समापन सीमांकक।)

usage() { 
    # No tabs necessary! 
    closing="That's all" 
    readarray message <<EOF 
     : Hello, this is a cool program. 
     : This should get unindented. 
     : This code should stay indented: 
     :  something() { 
     :   echo It works, yo!; 
     :  } 
     : $closing 
EOF 
    shopt -s extglob 
    printf '%s' "${message[@]#+(): }" 
    shopt -u extglob 
} 
0
geta() { 
    local _ref=$1 
    local -a _lines 
    local _i 
    local _leading_whitespace 
    local _len 

    IFS=$'\n' read -rd '' -a _lines ||: 
    _leading_whitespace=${_lines[0]%%[^[:space:]]*} 
    _len=${#_leading_whitespace} 
    for _i in "${!_lines[@]}"; do 
    printf -v "$_ref"[$_i] '%s' "${_lines[$_i]:$_len}" 
    done 
} 

gets() { 
    local _ref=$1 
    local -a _result 
    local IFS 

    geta _result 
    IFS=$'\n' 
    printf -v "$_ref" '%s' "${_result[*]}" 
} 

यह एक अलग दृष्टिकोण है जो एच को तत्वों के लिए printf के असाइनमेंट के कारण बैश 4.1 की आवश्यकता है। (पूर्व संस्करणों के लिए, नीचे geta फ़ंक्शन को प्रतिस्थापित करें)। यह मनमाने ढंग से अग्रणी व्हाइटस्पेस से संबंधित है, न केवल पूर्व निर्धारित राशि।

पहले समारोह, geta, stdin, स्ट्रिप्स प्रमुख खाली स्थान के से पढ़ता है और सरणी जिसका नाम में पारित किया गया था में परिणाम देता है।

दूसरा, gets, geta के रूप में एक ही बात करता है लेकिन एक भी स्ट्रिंग रिटर्न न्यूलाइन के साथ बरकरार (आखिरी को छोड़कर)।

यदि आप किसी मौजूदा चर के नाम को geta पर भेजते हैं, तो सुनिश्चित करें कि यह पहले से खाली है।

आह्वान geta तो जैसे:

$ geta hello <<'EOS' 
> hello 
> there 
>EOS 
$ declare -p hello 
declare -a hello='([0]="hello" [1]="there")' 

gets:

$ unset -v hello 
$ gets hello <<'EOS' 
>  hello 
>  there 
> EOS 
$ declare -p hello 
declare -- hello="hello 
there" 

यह दृष्टिकोण इतने लंबे समय के रूप में वे बाद के सभी पंक्तियों के लिए समान अक्षर हैं, अग्रणी खाली स्थान के पात्रों में से किसी भी संयोजन के लिए काम करना चाहिए। फ़ंक्शन पहली पंक्ति में अग्रणी व्हाइटस्पेस वर्णों की संख्या के आधार पर प्रत्येक पंक्ति के सामने से वर्णों की एक ही संख्या को स्ट्रिप करता है।

अंडरस्कोर के साथ शुरू होने वाले सभी चर का कारण पारित सरणी नाम के साथ नाम टकराव का मौका कम करना है। हो सकता है कि आप इसे फिर से लिखने के लिए कुछ भी लिखने के लिए फिर से लिखना चाहें। बैश से 4.1 पुराने के लिए

gets usage_message <<'EOS' 
    Hello, this is a cool program. 
    This should get unindented. 
    This code should stay indented: 
     something() { 
      echo It works, yo!; 
     } 
    That's all. 
EOS 

usage() { 
    printf '%s\n' "$usage_message" 
} 

जैसा कि बताया जा:

ओपी के समारोह में उपयोग करने के लिए

geta() { 
    local _ref=$1 
    local -a _lines 
    local _i 
    local _leading_whitespace 
    local _len 

    IFS=$'\n' read -rd '' -a _lines ||: 
    _leading_whitespace=${_lines[0]%%[^[:space:]]*} 
    _len=${#_leading_whitespace} 
    for _i in "${!_lines[@]}"; do 
    eval "$(printf '%s+=("%s")' "$_ref" "${_lines[$_i]:$_len}")" 
    done 
} 
संबंधित मुद्दे