मैं अपने .bashrc में त्रुटियों के कारण असमर्थित 'शॉप्ट' विकल्पों को कैसे रोक सकता हूं?


9

मैं अपेक्षाकृत विषम वातावरण में काम करता हूं जहां मैं अलग-अलग एचपीसी नोड्स, वीएम या मेरे व्यक्तिगत वर्कस्टेशन पर बैश के विभिन्न संस्करणों को चला सकता हूं। क्योंकि मैंने अपनी लॉगिन स्क्रिप्ट्स को एक Git repo में डाल दिया है, मैं .bashrcपूरे बोर्ड में एक ही (ish) का उपयोग करना चाहूंगा , बिना "अगर यह होस्ट, तो ..." - बहुत गड़बड़ है।

मुझे बैश I 4.1 का डिफ़ॉल्ट व्यवहार पसंद है जो कुंजी दबाने cd $SOMEPATHपर फैलता है । 4.2 और इसके बाद के संस्करण में, आपको इस व्यवहार को फिर से सक्षम करना होगा, और यह 4.2.29 तक उपलब्ध नहीं होगा । यह सिर्फ एक उदाहरण है, हालांकि; एक और, संभवतः संबंधित विकल्प, (हालांकि मुझे नहीं पता कि यह वास्तव में क्या करता है) ने भी v4.2 में डिफ़ॉल्ट व्यवहार को बदल दिया है।cd /the/actual/pathTabshopt -s direxpandshoptcomplete_fullquote

हालाँकि, direxpandबैश के पुराने संस्करणों द्वारा मान्यता प्राप्त नहीं है, और अगर मैं shopt -s direxpandअपने में कोशिश करता हूं .bashrc, तो हर बार जब मैं एक पुराने बैश के साथ नोड में लॉग इन करता हूं, तो कंसोल में मुद्रित होने वाले त्रुटि संदेश में परिणाम होता है:

-bash: shopt: direxpand: invalid shell option name

मैं जो करना चाहता हूं, वह सशर्त shop -s direxpandतरीके से Bash> 4.1 पर उस विकल्प को सक्षम करने के लिए चारों ओर एक सशर्त लपेट है , बिना Bash के पुराने संस्करणों ( यानी , केवल त्रुटि आउटपुट को पुनर्निर्देशित नहीं करके /dev/null)।


मेरे उत्तर ने कैसे मदद नहीं की?
लुसियानो अंड्रेस मार्टिनी

@LucianoAndressMartini यह किया है, और वह समाधान है जिसे मैंने अपने साथ जाना समाप्त कर दिया है .bashrc। मैं अभी भी $BASH_VERSINFOअपने स्वयं के संपादन के लिए चल रहे शेल के प्रमुख / लघु संस्करण का उपयोग करने के तरीके का एक रिकॉर्ड चाहता था , यही कारण है कि मैंने अपना उत्तर पोस्ट करना समाप्त कर दिया। :)
TheDudeAbides

मेरे उत्तर में देखो मेरे पास शेल स्क्रिप्ट के साथ प्रोग्राम संस्करण की तुलना करने के बारे में कुछ है।
लुसियानो अंड्रेस मार्टिनी

जवाबों:


14

जाँच करें कि direxpandक्या आउटपुट में मौजूद है shoptऔर अगर यह है तो इसे सक्षम करें:

shopt | grep -q '^direxpand\b' && shopt -s direxpand

4
बेहतर है कि grep -q '^direxpand\b'अगर भविष्य के किसी संस्करण या बैश के कांटे में कोई विकल्प हो, जिसमें विकल्प के रूप में यह शामिल हो और उसे हटा दिया जाए direxpand। इस विशिष्ट मामले में पूरी तरह से, लेकिन यह मजबूत होने के लिए ज्यादा खर्च नहीं करता है।
गिल्स एसओ- बुराई को रोकना '

धन्यवाद लुसियानो। मैंने अपने स्वयं के प्रश्न का उत्तर देने का इरादा किया था, लेकिन मैं अपने उत्तर को मेरे समीक्षा के बाद सहकर्मी समीक्षा के माध्यम से स्वीकार करूंगा। हो सकता है कि आप उन्हें स्वयं स्वीकार कर सकें?
TheDudeAbides

4
बैश विशिष्ट शेल विकल्पों को क्वेरी करने की अनुमति देता है, इसलिए कोई भी उपयोग कर सकता है [ -z "$(shopt -po direxpand 2>&-)" ] || shopt -s direxpand। कोई और अधिक रेगेक्स मुद्दे! :-)
डेविड फ़ॉस्टर

@DavidFoerster मैं तर्क को चारों ओर घुमा दूंगा: [ -n "blah" ] && shopt blahजिस तरह से आपने इसे वाक्यांश दिया है, आप कह रहे हैं "यदि direxpand असमर्थित है, तो यह काम न करें"।
रिच

1
@ रीच: मेरी अधिकांश शेल स्क्रिप्ट में set -eशीर्ष पर शामिल हैं , इसलिए मैं इस तरह से शॉर्ट-कट तर्क का उपयोग करता हूं।
डेविड फ़ॉस्टर

16

मैं यह नहीं देखता कि त्रुटियों को पुनर्निर्देशित करने में क्या गलत है /dev/null। यदि आप चाहते हैं कि आपका कोड मजबूत हो set -e, तो सामान्य मुहावरे का उपयोग करें … || true:

shopt -s direxpand 2>/dev/null || true

यदि आप विकल्प नहीं होने पर कुछ फ़ॉलबैक कोड चलाना चाहते हैं, तो shoptनिम्न स्थिति का उपयोग करें :

if shopt -s direxpand 2>/dev/null; then
   # the direxpand option exists
else
   # the direxpand option does not exist
fi

लेकिन अगर आप वास्तव में त्रुटि को पुनर्निर्देशित करना नापसंद करते हैं, तो आप आत्मनिरीक्षण करने के लिए पूर्ण तंत्र का उपयोग कर सकते हैं। यह मानता है कि आपके पास bash that 2.03 के साथ पुरातन मशीनें नहीं हैं जिनके पास प्रोग्राम पूरा होने योग्य नहीं है।

shopt_exists () {
  compgen -A shopt -X \!"$1" "$1" >/dev/null
}
if shopt_exists direxpand; then
  shopt -s direxpand
fi

यह विधि फोर्किंग से बचती है, जो कुछ वातावरण जैसे कि सिग्विन पर धीमी है। तो सीधा है 2>/dev/null, मुझे नहीं लगता कि आप प्रदर्शन पर उसे हरा सकते हैं।


यह वह जगह नहीं है जहां मेरा दिमाग चला गया है, लेकिन मुझे यह compgenप्रस्ताव पसंद है । कि varsity स्तर सामान वहीं है! से पुनर्निर्देशन से बचना /dev/nullसिर्फ एक व्यक्तिगत प्राथमिकता है। मैं माफी के बजाय अनुमति मांगना पसंद करता हूं, अगर यह समझ में आता है? :)
TheDudeAbides

बैश प्रोग्राम पूरी करने में पूरी तरह से बिना किसी स्कूली शिक्षा के लिए +1, जिसने मुझे मैनुअल में जाने के लिए मजबूर कर दिया, जिसका compgen -A shopt -X ...मतलब यह भी था।
TheDudeAbides

4
@ TheDudeAbides मैंने यूनिक्स और लिनक्सcompgen पर इस तरह का उपयोग करने के बारे में पढ़ा , मुझे नहीं पता कि पहले किसने इसे प्रस्तावित किया था। (मैं प्रोग्राम पूरा होने से पहले मेरे मुख्य शेल के रूप में बैश का उपयोग करना बंद कर दिया था।) प्रोग्रामिंग में यह आमतौर पर अनुमति के लिए पूछने के लिए एक बुरा विचार है क्योंकि एक जोखिम है कि अनुमति की जांच वास्तव में आप क्या कर रहे हैं, या तो एक कोडिंग के कारण मेल नहीं खाएगी। त्रुटि (जहाँ आप काफी जाँच नहीं कर रहे हैं कि आपको क्या लगता है कि आप जाँच कर रहे हैं) या क्योंकि आपने जो जाँच की थी, उसे इस्तेमाल करने से पहले आपने बदल दिया था
गिल्स एसओ- बुराई को रोकना '

5

जब आप निश्चित रूप से जानते हैं कि एक विशिष्ट shoptविकल्प बैश के एक निश्चित प्रमुख / मामूली / पैच रिलीज पर उपलब्ध है, तो आप इसे सशर्त रूप से सक्षम करने के लिए $BASH_VERSIONचर या $BASH_VERSINFO[]सरणी के तत्वों का निरीक्षण कर सकते हैं।

यहाँ बैश 4.2.29 या उससे अधिक के लिए एक परीक्षण है, वह संस्करण जहाँ direxpand पहली बार 4.2 श्रृंखला में पेश किया गया था :

if [[ $BASH_VERSION == 4.2.* && ${BASH_VERSINFO[2]} -ge 29 ]] ||
   [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -ge 3 ]] ||
   [[ ${BASH_VERSINFO[0]} -ge 5 ]]; then
    shopt -s direxpand
fi

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

नोट ब्रेसिज़ के आसपास है, जो कर रहे हैं के लिए आवश्यक है, और के उपयोग और है, जो पूर्णांक (स्थान पर निर्भर) शाब्दिक तुलना के बजाय है। यदि अयोग्य घोषित किया जाता है , तो ऑपरेटर के आरएचएस को बैश / सशर्त के भीतर "एक्सग्लोब" पैटर्न के रूप में माना जाता है , जैसा कि यहां उल्लेख किया गया है , जो एक रेगेक्स की तुलना में अधिक सौंदर्यवादी बनाता है, आईएमओ।${BASH_VERSINFO[index]}-eq-gt==[[]]

$BASH_VERSINFOसरणी सभी जानकारी के उत्पादन में देखते हैं शामिल हैं bash --version:

bash --version | head -1
# result:
# GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

declare -p BASH_VERSINFO
# result:
# declare -ar BASH_VERSINFO='([0]="4" [1]="3" [2]="48" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")'

जब यह प्रलेखन से स्पष्ट नहीं होता हैshopt जिसके लिए बैश संस्करण (s) समर्थित हो गया है या उनके व्यवहार को बदल दिया है, तो लुसियानो द्वारा प्रस्तावित विधि ठीक है:

# note the '-q' so that the matched pattern isn't actually printed
shopt | grep -q direxpand && shopt -s direxpand

... जैसा कि गाइल्स द्वारा प्रस्तावित समाधान में त्रुटि को नजरअंदाज करते हुए किया गया है ( shopt -s direxpand 2>/dev/null), और शायद $?पूरी तरह से जांच की जाए।

संदर्भ: 1 , 2 , 3
संबंधित पढ़ना: सेट और दुकान - क्यों दो?


आप भी कुछ का उपयोग करने में सक्षम हो सकते हैं if [[ $BASH_VERSION > 4.3 ]];( जैसे कि मैच 4.3.0, 5.0आदि, लेकिन यह भी 4.3.0-alpha। मुझे नहीं पता कि बाद के तथ्य मायने रखते हैं।)
ilkkachu

हाय @ilkkachu। बैश v5.x को कवर करने के लिए आपके संपादन के लिए धन्यवाद। direxpandविकल्प है, हालांकि बैश 4.2 के लिए वास्तव में उपलब्ध है; मैंने इसे v4.2.53 पर डॉकर छवि के साथ सत्यापित किया है docker run --rm bash:4.2 bash -c shopt | grep direxpand(और, अच्छे उपाय के लिए, कि यह वास्तव में v4.1.17 पर उपलब्ध नहीं है docker run --rm bash:4.1 bash -c shopt | grep direxpand)।
TheDudeAbides

आह ठीक है, मैंने परीक्षण किया 4.2.0और इस तथ्य पर ठोकर खाई कि यह वहां काम नहीं करता था। बदलाव का भी कहा गया है उस में जोड़ा bash-4.3-alpha। मुझे लगता है कि किसी को ${BASH_VERSINFO[2]}इसके बारे में सटीक होने के लिए जांच करने की आवश्यकता होगी , लेकिन मुझे नहीं पता कि किस बिंदु पर इसे जोड़ा गया ...
ilkkachu

मुझे लगता है कि हमने मूल रूप से ऊपर दिए गए बिंदु गिल्स को साबित कर दिया है; यह वास्तव में, शेल विकल्प को सक्षम करने का प्रयास करने के लिए बेहतर है , और फिर समर्थन नहीं होने पर त्रुटि से निपटें (या इसे दबाएं)।
TheDudeAbides
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.