2016-12-06 8 views
21

मुझे समझ में क्यों बैश दोहरे उद्धरण चिह्नों (लेकिन एक नहीं उद्धरण) को हटा जब, ${parameter:+word} (उपयोग वैकल्पिक मूल्य) के साथ चर विस्तार कर यहां-दस्तावेज़ में कोशिश कर रहा हूँ, उदाहरण के लिए:

% var=1 
% cat <<EOF 
> ${var:+"Hi there"} 
> ${var:+'Bye'} 
> EOF 
Hi there 
'Bye' 

अनुसार मैनुअल के लिए, :+ के बाद "शब्द" टिल्ड विस्तार, पैरामीटर विस्तार, कमांड प्रतिस्थापन, और अंकगणितीय विस्तार के साथ संसाधित किया जाता है। इनमें से कोई भी कुछ नहीं करना चाहिए।

मुझे क्या याद आ रही है? मैं विस्तार में दोहरे उद्धरण कैसे प्राप्त कर सकता हूं?

+1

एक बग या कार्यान्वयन लीकिंग की तरह लगता है। एक परिवर्तनीय को असाइन किए बिना वैकल्पिक मूल्य के रूप में डबल कोट का उपयोग करना असंभव है: 'dq = '' '; ... $ {var: + $ dq}' – choroba

+1

@choroba: '$ {var: + $ (गूंज '' ')}}' लेकिन मैं मूल रूप से सहमत हूं। उद्धृत पैरामीटर विस्तार में 'शब्द' की पार्सिंग में कुछ अजीब बात है (मैनुअल के मुताबिक, यहां दस्तावेज़ों में पैरामीटर विस्तार उद्धृत किए गए हैं, और यह मामला प्रतीत होता है।) – rici

+1

यहां लगभग समकक्ष दस्तावेज़ को एक गूंज "..." के रूप में देखा जा सकता है, और इस मामले में, "कमांड प्रॉम्प्ट पर" echo "$ {var: +" हाय वहाँ "} टाइप करके बस हटा दिया जाता है। वे उपयोग करते समय वापस आते हैं \ "लेकिन यहां दस्तावेज़ संगत नहीं है और \" इसके बजाय आउटपुट पर "उत्पन्न करता है। कुछ स्पष्ट रूप से सही नहीं है। – Gunstick

उत्तर

4

व्यवहार जानबूझकर दिखता है - यह मेरे द्वारा किए गए सभी बोर्न शैल में संगत है (उदा। Ksh93 और zsh वैसे ही व्यवहार करते हैं)।

व्यवहार इन विशेष विस्तारों के लिए केवल के लिए डबल-उद्धृत के रूप में इस दस्तावेज़ को इलाज के बराबर है। दूसरे शब्दों में, आप के लिए

$ echo "${var:+"hi there"}" 
hi there 
$ echo "${var:+'Bye'}" 
'Bye' 

ही परिणाम मिल वहाँ केवल POSIX कल्पना मैंने पाया कि कुछ खास पैरामीटर विस्तार में डबल उद्धृत शब्द के लिए होता है में एक बहुत ही बेहोश संकेत है। यह informative "Examples" section of Parameter Expansion से है:

पैटर्न के दोहरे उद्धरण डबल-कोट्स कहां रखा जाता है, इस पर निर्भर करता है।

"${x#*}"
< तारांकन > एक पैटर्न चरित्र है।
${x#"*"}
शाब्दिक < तारांकन > उद्धृत और विशेष नहीं है।

मैं दोहरे उद्धरण चिह्नों के लिए कि बोली हटाने शब्द पर लागू होता है सुझाव के रूप में अंतिम पंक्ति में लिखा होगा। यह उदाहरण सिंगल कोट्स के लिए समझ में नहीं आता है, और चूक से, सिंगल कोट्स के लिए कोई उद्धरण हटाने नहीं है।

अद्यतन

मैं FreeBSD /bin/sh है, जो एक Almquist शैल से ली गई है की कोशिश की। यह खोल सिंगल और डबल कोट्स आउटपुट करता है। तो व्यवहार अब सभी शैल में संगत नहीं है, केवल में शैल मैंने कोशिश की है।

:+ के बाद शब्द के विस्तार में डबल कोट्स प्राप्त करने के लिए के रूप में, मेरी ले

$ var=1 
$ q='"' 
$ cat <<EOF 
${var:+${q}hi there$q} 
EOF 
"hi there" 
3
$ cat <<EOF 
${var:+bare alt value is string already} 
${var:+'and these are quotes within string'} 
${var:+"these are double quotes within string"} 
${var:+"which are removed during substitution"} 
"${var:+but you can simply not substitute them away ;)}" 
EOF 
bare alt value is string already 
'and these are quotes within string' 
these are double quotes within string 
which are removed during substitution 
"but you can simply not substitute them away ;)" 

नोट है, जो यहाँ-दस्तावेज़ इस पुन: पेश करने की जरूरत नहीं है:

$ echo "${var:+'foo'}" 
'foo' 
11

टीएल; डॉ

$ var=1; cat <<EOF 
"${var:+Hi there}" 
${var:+$(printf %s '"Hi there"')} 
EOF 
"Hi there" 
"Hi there" 

वैकल्पिक मूल्य में डबल कोट्स शामिल करने के लिए दो व्यावहारिक कामकाज।
एम्बेडेड $(...) दृष्टिकोण अधिक बोझिल है, लेकिन अधिक लचीला है: यह एम्बेडेड डबल कोट्स को शामिल करने की अनुमति देता है और आपको यह भी नियंत्रित करता है कि मूल्य का विस्तार किया जाना चाहिए या नहीं।


Jens's helpful answer और Patryk Obara's helpful answer दोनों पर प्रकाश डाला और आगे समस्या का प्रदर्शन।

ध्यान दें कि समस्याग्रस्त व्यवहार समान रूप से पर लागू होता है:

  • नियमित डबल-कोटेड तार (के रूप में अन्य उत्तर में बताया गया है) (जैसे, echo "${var:+"Hi there"}"; 1 वैकल्पिक हल के लिए, आप चाहते दिलचस्प, Gunstick के रूप में अंक प्रश्न पर एक टिप्पणी में बाहर विकल्प मूल्य में \"का उपयोग करके उत्पादन के लिए, जैसे, echo "\"${var:+Hi there}\""; \" उदाहरणों आसपास -quote करने के लिए है उत्पादन मेंडबल-कोटेड तार में काम करता है - जैसे, echo "${var:+\"Hi th\"ere\"}" -। गैर उद्धृत यहां-डॉक्स में विपरीत)

  • संबंधित विस्तार${var+...}, ${var-...}/${var:-...}, और ${var=...}/${var:=...}

  • इसके अलावा, \ के संबंध में संबंधित विषमता है- को डबल-उद्धृत वैकल्पिक मानों के अंदर डबल-उद्धृत स्ट्रिंग/अनकॉक्टेड इन-डॉक के अंदर: bash और ksh अप्रत्याशित रूप से एम्बेडेड \ उदाहरण हटाएं; उदाहरण के लिए,
    echo "${nosuch:-"a\b"}" अनपेक्षित रूप से ab उत्पन्न करता है, भले ही echo "a\b" अलगाव पैदावार में a\b - this question देखें।

मैं व्यवहार के लिए कोई स्पष्टीकरण[1] , लेकिन मैं व्यावहारिक समाधान कि सभी प्रमुख POSIX संगत गोले (dash, bash, ksh, zsh) के साथ काम की पेशकश कर सकते हैं:

ध्यान दें कि " उदाहरणों विकल्प मूल्य अंदर वाक्यात्मक कारणों के लिए की जरूरत कभी नहीं कर रहे हैं: वैकल्पिक मूल्य निहित एक डबल-उद्धृत स्ट्रिंग की तरह व्यवहार किया जाता है: कोई टिल्डे विस्तार नहीं, कोई शब्द-विभाजन नहीं होता है, और कोई ग्लोबिंग नहीं होता है, लेकिन पैरामीटर विस्तार, अंकगणितीय विस्तार और कमांड प्रतिस्थापन प्रदर्शन किया जाता है।

नोट पैरामीटर प्रतिस्थापन या उपसर्ग/प्रत्यय-हटाने, को शामिल विस्तार में उद्धरण कि वाक्यात्मक अर्थ है; उदाहरण: echo "${BASH#*"bin"}" या echo "${BASH#*'bin'}" - उत्सुकता से, dash एकल उद्धरणों का समर्थन नहीं करता है, हालांकि।

  • आप चाहते हैं उद्धरण साथ पूरे विकल्प मूल्य के चारों ओर, और यह कोई एम्बेडेड उद्धरण है और आप चाहते हैं कि उसे विस्तार,
    पूरे विस्तार बोली , जो वैकल्पिक मूल्य से " हटाने की समस्या को छोड़ देता है:

    # Double quotes 
    $ var=1; cat <<EOF 
    "${var:+The closest * is far from $HOME}" 
    EOF 
    "The closest * is far from /Users/jdoe" 
    
    # Single quotes - but note that the alternative value is STILL EXPANDED, 
    # because of the overall context of the unquoted here-doc. 
    var=1; cat <<EOF 
    '${var:+The closest * is far from $HOME}' 
    EOF 
    'The closest * is far from /Users/jdoe' 
    
  • एम्बेडेड उद्धरण के लिए, या करने के लिए विकल्प मूल्य के विस्तार को रोकने,
    , एक एम्बेडेड आदेश प्रतिस्थापन (गैर उद्धृत का उपयोग हालांकि यह है कि यह व्यवहार करते हैं जाएगा उद्धृत किया गया था):

    # Expanded value with embedded quotes. 
    var=1; cat <<EOF 
    ${var:+$(printf %s "We got 3\" of snow at $HOME")} 
    EOF 
    We got 3" of snow at /Users/jdoe 
    
    # Literal value with embedded quotes. 
    var=1; cat <<EOF 
    ${var:+$(printf %s 'We got 3" of snow at $HOME')} 
    EOF 
    We got 3" of snow at $HOME 
    

इन दो दृष्टिकोणों को आवश्यकतानुसार जोड़ा जा सकता है।


[1] वास्तव में, विकल्प मूल्य:

  • बर्ताव करता है एक परोक्ष डबल-कोटेड स्ट्रिंग की तरह,
  • ' उदाहरणों, नियमित रूप से डबल-कोटेड तार के रूप में , अक्षर के रूप में माना जाता है।

ऊपर देखते हुए

  • यह मतलब भी शाब्दिक रूप " उदाहरणों एम्बेडेड के इलाज के लिए होता है, और बस, उन्हें के माध्यम से पारित सिर्फ ' उदाहरणों की तरह।
    इसके बजाय, उदासी, वे कर रहे हैं
    हटा दिया, और यदि आप उन्हें \" के रूप में भागने की कोशिश, \ भी (डबल-कोटेड तार के अंदर गैर उद्धृत यहाँ-दस्तावेजों के अंदर है, लेकिन दिलचस्प नहीं) को बनाए रखा है, में छोड़कर ksh - प्रशंसनीय अपवाद -, जहां \ उदाहरण हटा दिए गए हैं। zsh में, दिलचस्प, \" टूटता विस्तार पूरी तरह (सभी गोले में असंतुलित नहीं छोड़ा जाएगा लोगों करते हैं) का उपयोग करने की कोशिश कर।

    • अधिक विशेष रूप से, डबल कोट विकल्प मूल्य में कोई वाक्यात्मक समारोह है, लेकिन वे कर रहे हैं पार्स रूप में यदि वे किया: उद्धरण हटाने लागू किया जाता है, और आप उपयोग नहीं कर सकते (असंतुलित) " उदाहरणों \" के बिना इंटीरियर में - उनसे बचने (जो, जैसा कि कहा गया है, बेकार है, क्योंकि \ उदाहरण बनाए रखा गया है)।

निहित डबल-कोटेड स्ट्रिंग अर्थ विज्ञान को देखते हुए, शाब्दिक $ उदाहरणों या तो \$ -escaped होना चाहिए, या एक आदेश प्रतिस्थापन एक एकल उद्धृत स्ट्रिंग ($(printf %s '...')) एम्बेड करने के लिए इस्तेमाल किया जाना चाहिए।

+0

मुझे लगता है कि एम्बेडेड '" को अक्षर के रूप में माना जाता है, और फिर बैश मूल्य मूल्यांकन करने पर हटा दिया जाता है। लेकिन इससे मुझे उत्सुकता मिलती है, क्यों उपसर्ग/प्रत्यय निष्कासन लगातार व्यवहार नहीं करता है। मुझे लगता है कि मुझे बैश स्रोत कोड में देखना होगा उलझन में, वास्तव में क्या हो रहा है ... –

+0

@PatrykObara: यह बिल्कुल असंगतता है: डबल कोट्स में वैकल्पिक मान में कोई वाक्य रचनात्मक _function_ नहीं है, लेकिन उन्हें _parsed हैं जैसे कि उन्होंने किया था: उद्धरण हटाने को लागू किया गया है, जैसा कि आप वर्णन करते हैं, और आप '' 'उदाहरणों का उपयोग नहीं कर सकते इंटीरियर बिना \ "' से बच रहा है (जो बेकार है, क्योंकि '\' बनाए रखा गया है)। – mklement0

+2

@PatrykObara: अंतर अप्रत्याशित हो सकता है, लेकिन उपसर्ग/प्रत्यय निष्कासन और स्ट्रिंग प्रतिस्थापन के संदर्भ में _does_ उद्धरण एक उपयोगी कार्य प्रदान करता है: पैटर्न मेटाएक्टएक्टर्स (उदाहरण के लिए, '*') को शाब्दिक से अलग करने के लिए (उदाहरण के लिए, '" * "'), इसलिए मैं इसे एक असंगतता नहीं कहूंगा। – mklement0

संबंधित मुद्दे