अगर यह खाली है तो मैं किसी उद्धृत चर का विस्तार कैसे कर सकता हूं?


21

कहो कि मेरे पास एक स्क्रिप्ट है:

some-command "$var1" "$var2" ...

और, उस घटना में जो var1खाली है, मैं चाहता हूं कि इसे खाली स्ट्रिंग के बजाय कुछ भी नहीं बदला जाए, ताकि कमांड निष्पादित हो:

some-command "$var2" ...

और नहीं:

some-command '' "$var2" ...

क्या चर का परीक्षण करने और इसे सहित सशर्त रूप से सरल तरीका है?

if [ -n "$1" ]; then
    some-command "$var1" "$var2" ...
    # or some variant using arrays to build the command
    # args+=("$var1")
else
    some-command "$var2" ...
fi

क्या बाश, ज़ीश, या जैसे कुछ भी नहीं करने के लिए विस्तार से एक पैरामीटर प्रतिस्थापन है? मैं अभी भी बाकी तर्कों में ग्लोबिंग का उपयोग करना चाह सकता हूं, इसलिए इसे अक्षम करना और चर को हटाना विकल्प नहीं है।


मुझे पता था कि मैंने इसे पहले देखा था और शायद इसका इस्तेमाल किया था, लेकिन इसे खोजना मुश्किल साबित हुआ। : अब है कि माइकल वाक्य रचना से पता चला है, मुझे याद है, जहां मैं पहली बार इसे जल्दी पर्याप्त देखा था unix.stackexchange.com/a/269549/70524 , unix.stackexchange.com/q/68484/70524
muru

यदि आप जानते हैं कि यह किसी प्रकार का पैरामीटर प्रतिस्थापन है, तो आपने पृष्ठ के पैरामीटर विस्तार अनुभाग को क्यों नहीं देखा man? (-;
फिलिप्पुस

1
@Philippos मुझे नहीं पता था कि यह उस समय क्या था, केवल मैंने इसे देखा था या पहले इसका इस्तेमाल किया था। ज्ञात अज्ञात और ज्ञात। :(
मुरु

1
प्रश्न में ही तर्क रखने के लिए एक सरणी का उपयोग करते हुए उल्लेख करने के लिए अतिरिक्त कुकी अंक।
15:लक्काचु

जवाबों:


29

पॉज़िक्स आज्ञाकारी गोले और बैश हैं ${parameter:+word} :

यदि पैरामीटर अशांत या अशक्त है, अशक्त प्रतिस्थापित किया जाएगा; अन्यथा, शब्द का विस्तार (या यदि शब्द छोड़ा गया है तो एक रिक्त स्ट्रिंग ) प्रतिस्थापित किया जाएगा।

तो आप बस कर सकते हैं:

${var1:+"$var1"}

और var1इसकी जाँच की जा सकती है, और "$var1"यदि यह सेट की गई है और गैर-रिक्त है (साधारण डबल-क्वैटिंग नियमों के साथ) तो इसका उपयोग किया जा सकता है। अन्यथा इसका विस्तार कुछ भी नहीं है। ध्यान दें कि यहां केवल आंतरिक भाग को उद्धृत किया गया है, न कि पूरी बात को।

वही zsh में भी काम करता है। आपको चर को दोहराना है, इसलिए यह आदर्श नहीं है, लेकिन यह ठीक उसी तरह से काम करता है जैसा आप चाहते थे।

यदि आप एक खाली तर्क का विस्तार करने के लिए एक सेट-लेकिन-खाली चर चाहते हैं, तो ${var1+"$var1"}इसके बजाय का उपयोग करें ।


1
मेरे लिए काफी अच्छा। तो, इसमें, पूरी बात उद्धृत नहीं है, केवल wordभाग है।
मुरु

1
जैसा कि "बैश, ज़श, या लाइक" (और प्रश्नोत्तर संग्रह के लिए) के लिए पूछे गए प्रश्न के अनुसार, मैंने यह दर्शाने के लिए संपादन किया कि यह एक पॉज़िक्स फीचर है। यहां तक ​​कि, यदि आप मेरी टिप्पणी के बाद प्रश्न में / bash टैग जोड़ते हैं। (-;
फिलिप्पुस

2
मैंने संपादन की स्वतंत्रता को अंतर के बीच लिया :+और +
ilkachachu

POSIX- अनुरूप समाधान के लिए बहुत बहुत धन्यवाद! मैं संभावित चोकेपॉइंट स्क्रिप्ट्स का उपयोग sh/ उपयोग करने की कोशिश करता हूं dash, इसलिए मैं हमेशा इसकी सराहना करता हूं जब कोई व्यक्ति यह दर्शाता है कि बैश का सहारा लिए बिना कोई चीज कैसे संभव है।
जेम्सअव्रीड्यूड

मैं इसके विपरीत प्रभाव की तलाश में था (अगर यह शून्य के रूप में शुरू होता है तो कुछ और विस्तार करें)। यह पता चलता है कि इस तर्क को + में - जैसे: $ {खाली_वर: -प्रस्थान} से बदलकर उल्टा किया जा सकता है
एलेक्स जानसेन

5

zshजब आप उद्धरण छोड़ते हैं तो डिफ़ॉल्ट रूप से यही होता है:

some-command $var1 $var2

असल में, एकमात्र कारण जिसकी आपको अभी भी पैरामीटर विस्तार के आसपास zsh में उद्धरण की आवश्यकता है, उस व्यवहार (खाली हटाने) से बचने के लिए zshहै क्योंकि अन्य समस्याएं जो अन्य शेल को प्रभावित नहीं करती हैं , जब आप पैरामीटर विस्तार (अव्यक्त विभाजन) को उद्धृत नहीं करते हैं। ग्लोब)

यदि आप विभाजन और ग्लोब को अक्षम करते हैं तो आप अन्य POSIX जैसे गोले के साथ भी ऐसा कर सकते हैं:

(IFS=; set -o noglob; some-command $var1 $var2)

अब, मैं तर्क दूंगा कि यदि आपके चर में 0 या 1 मान हो सकता है, तो यह एक सरणी होना चाहिए और स्केलर चर और उपयोग नहीं होना चाहिए:

some-command "${var1[@]}" "${var2[@]}"

और तब उपयोग करें var1=(value)जब var1किसी एक मान को शामिल करना है, var1=('')जब एक खाली मान रखना है, और var1=()जब इसका कोई मूल्य नहीं है


0

मैं इसे bash स्क्रिप्ट में rsync का उपयोग करके चलाता था जिसने -nसूखी रन को टॉगल करने के साथ या उसके बिना कमांड शुरू किया था । यह पता चला है कि rsync और कई ग्नू कमांड ''एक मान्य प्रथम तर्क के रूप में लेते हैं और यदि यह नहीं था तो अलग तरीके से कार्य करते हैं।

इसने डिबग में काफी समय लिया क्योंकि अशक्त पैरामीटर लगभग पूरी तरह से अदृश्य हैं।

Rsync सूची में किसी ने मुझे इस समस्या से बचने का एक तरीका भी दिखाया बहुत मेरी कोडिंग सरल बनाने। अगर मैं इसे सही तरीके से समझूं, तो यह @ स्टीफन चेज़ेलस के अंतिम सुझाव पर एक बदलाव है।

कई अलग-अलग चर में अपने कमांड तर्क बनाएं। इन्हें किसी भी क्रम या तर्क में सेट किया जा सकता है जो समस्या के अनुकूल हो।

फिर, अंत में, चर का उपयोग करके इसकी उचित जगह में सब कुछ के साथ एक सरणी का निर्माण करें और वास्तविक कमांड के तर्क के रूप में उपयोग करें।

इस प्रकार आदेश केवल तर्कों की प्रत्येक भिन्नता के लिए दोहराया जाने के बजाय कोड में एक स्थान पर जारी किया जाता है।

कोई भी चर जो खाली है वह इस विधि का उपयोग करके गायब हो जाता है।

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

उदाहरण:

dry_run=''
if [[ it is a test run ]]
then
  dry_run='-n'
fi
...
rsync_options=(
  ${dry_run}
  -avushi
  ${delete}
  ${excludes}
  --stats
  --progress
)
...
eval rsync "${rsync_options[@]}" ...

यह मेरे द्वारा प्रश्न में दिए गए कार्यों को करने का एक बदतर तरीका है (सशर्त रूप से तर्कों की एक सरणी का निर्माण)। चरों को निर्विवाद रूप से छोड़ने से, कौन जानता है कि आप अपने आप को किन समस्याओं के लिए खुला छोड़ रहे हैं।
मुरु

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


बस इसी में वापस आ गया। उदाहरण के लिए धन्यवाद। यह समझ में आता है। मैं इसके साथ काम करने जा रहा हूं।
जो

मेरे पास यहां समान उपयोग का मामला है, लेकिन आप कुछ इस तरह से कर सकते हैं: अगर ["$ सूखी" == "सच"]; फिर सूखा = "- एन"; फाई ... तो अगर वेरिएबल ड्राई है, तो आप इसे बनाते हैं -n, और फिर आप हमेशा की तरह अपना rsync कमांड बनाते हैं और इसे इस तरह से बनाते हैं: rsync $ {dry1: + "$ dry1"} ... अगर यह शून्य है कुछ नहीं होगा, अन्यथा यह आपकी आज्ञा में बन जाएगा
फ्रीडो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.