बैश स्थानापन्न प्रतिस्थापन में बैश को खाने के लिए नहीं है?
उदाहरण के लिए:
var=`echo line one && echo line two`
echo $var
line one line two
मैं जो चाहता हूं
var=`echo line one && echo line two` # plus some magic
echo $var
line one
line two
बैश स्थानापन्न प्रतिस्थापन में बैश को खाने के लिए नहीं है?
उदाहरण के लिए:
var=`echo line one && echo line two`
echo $var
line one line two
मैं जो चाहता हूं
var=`echo line one && echo line two` # plus some magic
echo $var
line one
line two
जवाबों:
यह बैकटिक्स प्रतिस्थापन के साथ एक मुद्दा नहीं है, लेकिन इसके साथ echo
; आपको काम करने वाले नियंत्रण पात्रों को प्राप्त करने के लिए चर को उद्धृत करना होगा:
$ var=`echo line one && echo line two`
$ echo "$var"
line one
line two
bash
एक कमांड को क्रियान्वित के हवाले से पहले प्रदर्शन मानकों विस्तार को सूचित करने के लिए आवश्यक है bash
कि आप एक ही स्ट्रिंग और नहीं 4 शब्द प्रिंट करना चाहते हैं ( line
, one
, line
और two
)। कोशिश करो: echo a <many spaces> b
और echo "a <many spaces> b"
। इस जवाब पर भी एक नजर डालिए।
भले ही @ साइरस सही है - यह वास्तव में पूरे सवाल का जवाब नहीं देता है, और क्या हो रहा है इसका कोई स्पष्टीकरण नहीं है।
तो इससे चलने दो।
पहले बाइट अनुक्रम निर्धारित करें जो अपेक्षित है:
$ { echo a; echo b; } | xxd
0000000: 610a 620a a.b.
अब, बाइट अनुक्रम को पकड़ने के प्रयास के लिए कमांड सबस्टीट्यूशन (सेक्शन 3.5.4) का उपयोग करें :
$ x=$( echo a; echo b; )
फिर, बाइट अनुक्रम को सत्यापित करने के लिए एक सरल गूंज करें:
$ echo $x | xxd
0000000: 6120 620a a b.
ऐसा लगता है कि पहली नई लाइन को एक स्थान के साथ बदल दिया गया था, और दूसरी नई पंक्ति को बरकरार रखा गया था। पर क्यों ?
आइए देखें कि वास्तव में यहाँ क्या हो रहा है:
सबसे पहले, बैश शेल पैरामीटर विस्तार (धारा 3.5.3) करेगा
'$' चरित्र पैरामीटर विस्तार, कमांड प्रतिस्थापन या अंकगणितीय विस्तार का परिचय देता है। विस्तार किए जाने वाले पैरामीटर नाम या प्रतीक को ब्रेसिज़ में संलग्न किया जा सकता है, जो वैकल्पिक हैं, लेकिन चर को वर्णों से विस्तारित करने के लिए इसे बाद में संरक्षित किया जा सकता है, जिसे नाम के भाग के रूप में व्याख्या किया जा सकता है।
फिर बैश करेंगे वर्ड स्प्लिटिंग (धारा 3.5.7)
शेल पैरामीटर विस्तार, कमांड प्रतिस्थापन, और अंकगणितीय विस्तार के परिणामों को स्कैन करता है जो शब्द बंटवारे के लिए दोहरे उद्धरणों में नहीं हुआ था।
शेल $ IFS के प्रत्येक चरित्र को एक सीमांकक के रूप में मानता है, और इन वर्णों पर अन्य विस्तार के परिणामों को शब्दों में विभाजित करता है। यदि IFS परेशान है, या इसका मूल्य ठीक है, ...
अगला, बैश इसे एक साधारण आदेश के रूप में मानेंगे (धारा 3.2.1)
एक साधारण कमांड उस तरह की कमांड है जिसका सामना अक्सर किया जाता है। यह केवल शब्दों का एक क्रम है, जो शेल के नियंत्रण ऑपरेटरों (परिभाषाएँ देखें) द्वारा समाप्त किए गए रिक्त स्थान से अलग है। पहला शब्द आम तौर पर एक कमांड को निष्पादित करता है, बाकी शब्दों के साथ उस कमांड के तर्क होते हैं।
रिक्त की परिभाषा (धारा 2 - परिभाषाएँ)
रिक्त स्थान या टैब वर्ण।
अंत में, बैश इको (धारा 4.2 - बैश बिलिन कमांड्स) आंतरिक कमांड को आमंत्रित करता है
... रिक्त स्थान द्वारा अलग किए गए आर्ग्स का आउटपुट, एक नई रेखा के साथ समाप्त किया गया। ...
इसलिए संक्षेप में, शब्द विभाजन से नई कड़ियों को हटा दिया जाता है, और फिर प्रतिध्वनि को 2 आर्ग, "ए", और "बी" मिलते हैं, और फिर उन्हें रिक्त स्थान द्वारा अलग किया जाता है और एक नई रेखा के साथ समाप्त होता है।
@Cyrus ने जो सुझाव दिया है उसे करना (और इको से एनलाइन को दबाएं -n) परिणाम बेहतर है:
$ echo -n "$x" | xxd
0000000: 610a 62 a.b
हालांकि यह अभी भी सही नहीं है, अनुगामी न्यूलाइन चला गया है। कमांड प्रतिस्थापन (धारा 3.5.4) के करीब देखना :
बैश कमांड निष्पादित करके और कमांड प्रतिस्थापन को कमांड के मानक आउटपुट के साथ बदल देता है, जिसमें कोई भी नई सीमाएं हटा दी जाती हैं।
अब यह स्पष्ट है कि नई लाइन क्यों चली जाती है, इसे बनाए रखने में धोखा दिया जा सकता है। ऐसा करने के लिए, अंत में एक अतिरिक्त स्ट्रिंग जोड़ें, और चर का उपयोग करते समय इसे हटा दें:
$ x=$( echo a; echo b; echo -n extra )
$ echo -n "${x%extra}" | xxd
0000000: 610a 620a a.b.
आउटपुट के अंत में अतिरिक्त भाग जोड़ें, और चर को उद्धृत करें:
$ cat /no/file/here 2>&1 | xxd
0000000: 6361 743a 202f 6e6f 2f66 696c 652f 6865 cat: /no/file/he
0000010: 7265 3a20 4e6f 2073 7563 6820 6669 6c65 re: No such file
0000020: 206f 7220 6469 7265 6374 6f72 790a or directory.
$ cat /no/file/here 2>&1 | cksum
3561909523 46
$
$ var=$( cat /no/file/here 2>&1; rc=${?}; echo extra; exit ${rc})
$ echo $?
1
$
$ echo -n "${var%extra}" | xxd
0000000: 6361 743a 202f 6e6f 2f66 696c 652f 6865 cat: /no/file/he
0000010: 7265 3a20 4e6f 2073 7563 6820 6669 6c65 re: No such file
0000020: 206f 7220 6469 7265 6374 6f72 790a or directory.
$ echo -n "${var%extra}" | cksum
3561909523 46
मैंने cYrus के उत्तर पर एक टिप्पणी में अपना छोटा सा जोड़ दिया होगा, लेकिन मैं अभी तक उन उत्तरों पर टिप्पणी नहीं कर सकता जो मुझे लगता है। इसलिए मैं पूर्णता के लिए उनके उत्तर के हिस्से को दोहराऊंगा।
आपके कोड की पहली पंक्ति में जो होता है, वह यह है कि वास्तव में बैकटिक्स प्रतिस्थापन, प्रलेखित कमांड के आउटपुट के अनुगामी न्यूलाइन्स को दस्तावेज के रूप में खाता है । लेकिन यह आपकी दो लाइनों के बीच की नई रेखा को नहीं खाता है।
कोड की दूसरी पंक्ति में क्या होता है कि गूंज को दो तर्कों के साथ निष्पादित किया जाता है, पहली और दूसरी पंक्ति। विस्तारित चर को उद्धृत करने से वह ठीक हो जाएगा: echo "$var"
यह आपकी पंक्ति एक और पंक्ति दो के बीच की नई रेखा को संरक्षित करेगा। और echo
डिफ़ॉल्ट रूप से एक अनुगामी न्यूलाइन जोड़ देगा ताकि सब कुछ ठीक हो जाए।
अब यदि आप कुछ कमांड प्रतिस्थापन के आउटपुट में सभी अनुगामी newlines को संरक्षित करना चाहते हैं, तो वर्कअराउंड एक और लाइन आउटपुट जोड़ने के लिए है, जिसे आप कमांड प्रतिस्थापन के बाद हटा सकते हैं, यहां देखें ।