यदि कई चर सेट हैं तो टेस्ट करें


19

मैं यह सुनिश्चित करना चाहता हूं कि एक स्क्रिप्ट के एक निश्चित बिंदु पर, sourceएक कॉन्फ़िगरेशन फ़ाइल के बाद , कई चर निर्धारित किए जाते हैं और, यदि वे निष्पादन को रोकने के लिए नहीं हैं, तो उपयोगकर्ता को लापता चर के बारे में बताएं। मैंने कोशिश की है

for var in $one $two $three ; do
    ...

लेकिन अगर उदाहरण के लिए $twoसेट नहीं किया गया है, तो लूप को कभी भी निष्पादित नहीं किया जाता है $two। अगली चीज़ जो मैंने कोशिश की थी

for var in one two three ; do
    if [ -n ${!var} ] ; then
        echo "$var is set to ${!var}"
    else
        echo "$var is not set"
    fi
done

लेकिन अगर दो सेट नहीं है, तो मुझे अभी भी "दो सेट है" के बजाय "दो सेट नहीं है"।

मैं यह कैसे सुनिश्चित कर सकता हूं कि सभी आवश्यक चर सेट हैं?

अद्यतन / समाधान: मुझे पता है कि "सेट" और "सेट, लेकिन खाली" के बीच अंतर है। अब मैं उपयोग करता हूं ( /programming//a/16753536/3456281 और इस सवाल के जवाब के लिए धन्यवाद ) निम्नलिखित हैं:

if [ -n "${!var:-}" ] ; then

इसलिए, यदि varसेट किया गया है, लेकिन खाली है, तब भी इसे अमान्य माना जाता है।


1
set -uजब कोई अनसेट चर का उपयोग किया जाता है, तो आप इसे तुरंत समाप्त करने के लिए अपनी स्क्रिप्ट की शुरुआत में भी जोड़ सकते हैं ।
n.st

जवाबों:


8

उद्धृत करने की त्रुटि।

if [ -n "${!var}" ] ; then

भविष्य के लिए: सेटिंग

set -x

कोड चलाने से पहले आपको समस्या दिखाई गई होगी। उस कोड में जोड़ने के बजाय आप अपनी स्क्रिप्ट के साथ कॉल कर सकते हैं

bash -vx ./my/script.sh

यह काम करता है, लेकिन / उद्धरण चिह्नों के साथ क्या हो रहा है? क्या मेरा सामान्य दृष्टिकोण पहली जगह सही है?
जस्पर

हाँ, यह संज्ञानात्मक है: मैंने सवाल पूछा था कि इससे पहले कि यह पूछा ... 8-)
हौके लैगिंग

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

इसके विपरीत, उद्धरण केवल विस्तार से बचाता है। यदि विस्तार में आप रुचि रखते हैं, तो उद्धृत करना निश्चित रूप से जाने का तरीका नहीं है। उदाहरण के लिए: सीएस = 673,290,765, सेट - $ (IFS =; इको $ cs); गूंज $ #; आउटपुट: 3
mikeserv

2
@ मोटरसाइकल केवल एकल उद्धरण विस्तार के खिलाफ रक्षा करते हैं जो मैं स्पष्ट रूप से सुझाव नहीं देता हूं। डबल कोट्स शब्द विभाजन के विरुद्ध रक्षा करते हैं। मैंने इस बात से इनकार नहीं किया है कि ऐसे मामले हो सकते हैं जहाँ उद्धृत करना छोड़ना होगा। लेकिन यह मेरे सामान्य नियम के खिलाफ एक तर्क नहीं है। किस तरह के लोग कुछ का उपयोग करने जा रहे हैं set -- $(IFS=, ; echo $cs)? जिस तरह के लोगों को यहां पूछना if [ -n ${!var} ] ; thenपड़ता है वह काम क्यों नहीं करता है? शायद ऩही।
हॉके लैगिंग

5

केवल एक चीज जो आपको चाहिए वह है आपके परीक्षण में उद्धरण:

for var in one two three ; do
    if [ -n "${!var}" ] ; then
        echo "$var is set to ${!var}"
    else
        echo "$var is not set"
    fi
done

मेरे लिये कार्य करता है।


4

यदि आप चाहते हैं कि कार्यक्रम बंद हो जाए:

N= 
${one?var 1 is unset} 
${two:?var 2 is unset or null}
${three:+${N:?var 3 is set and not null}}

वह चाल चलेंगे। प्रश्न चिह्न का अनुसरण करने वाले प्रत्येक संदेश को मुद्रित किया जाता है stderrऔर अभिभावक शेल की मृत्यु हो जाती है। ठीक है, ठीक है, इसलिए प्रत्येक संदेश नहीं - केवल एक - बस पहला वाला जो एक संदेश को प्रिंट करने में विफल रहता है क्योंकि खोल मर जाता है। मुझे इन परीक्षणों का उपयोग करना पसंद है:

( for v in "$one" "$two" "$three" ; do
    i=$((i+1)) ; : ${v:?var $i is unset or null...} 
done ) || _handle_it

मुझे यहाँ इस बारे में और भी बहुत कुछ कहना था ।


2

आप जोड़ सकते हो

set -u

आपकी स्क्रिप्ट की शुरुआत इसे समाप्त करने के लिए करती है जब यह एक परेशान चर का उपयोग करने की कोशिश करता है।

जैसी स्क्रिप्ट

#!/bin/sh
set -u
echo $foo

में परिणाम होगा

script.sh: 3: script.sh: foo: पैरामीटर सेट नहीं है

यदि आप bashइसके बजाय उपयोग कर रहे हैं , तो त्रुटि इस तरह दिखाई देगी:

script.sh: पंक्ति 3: foo: अनबाउंड वैरिएबल


और आपकी राय में यह रन टाइम चेक के लिए किस मायने में मायने रखता है?
हउक लागिंग

2
@HaLLaging मैं आपको काफी फॉलो नहीं करता - set -uओपी से बचने की कोशिश कर रहा है और (अन्य सभी समाधानों के विपरीत) चर के एक विशिष्ट सेट तक सीमित नहीं है। यह वास्तव में लगभग सभी शेल लिपियों के लिए एक उपयोगी एहतियात है, जब एक चरखी बेकार होने पर अप्रत्याशित चीजें करने के बजाय उन्हें सुरक्षित रूप से विफल कर दिया जाता है। यह लेख विषय पर एक उपयोगी संदर्भ है।
n

@ n.st I असहमत - अशक्त केवल एक मूल्य के रूप में उपयोगी हो सकता है यदि आप इसके लिए योजना बनाते हैं तो अशक्त नहीं है।
8

1
@ n.st इसका ओपी के लिए कोई मतलब नहीं है क्योंकि वह असंतुष्ट चर (बीटीडब्लू: एक सेट लेकिन खाली चर को एक्सेस करने के खिलाफ सुरक्षा नहीं चाहता है, लेकिन वही त्रुटि का कारण बनेगा और न ही आपकी "सुरक्षा" पर प्रतिक्रिया देगा)। वह एक रन टाइम चेक चाहता है कि क्या कोई वेरिएबल अनसेट / खाली है। आपका सुझाव सामान्य विकास सहायता के रूप में उपयोगी हो सकता है लेकिन ओपी की समस्या का समाधान नहीं करता है।
हौके लैगिंग

set -uमुझे लगता है कि इस्तेमाल किया जा सकता है, लेकिन यह उचित पैरामीटर विस्तार के रूप में लचीला नहीं है (मेरे अद्यतन प्रश्न देखें)। और set -uअगर मुझे एक स्थान पर उनकी उपस्थिति की जांच करनी है तो मुझे सभी लक्ष्य चर तक डमी-एक्सेस करना होगा।
जस्पर

2

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

#!/bin/bash

required_vars=(one two three)

missing_vars=()
for i in "${required_vars[@]}"
do
    test -n "${!i:+y}" || missing_vars+=("$i")
done
if [ ${#missing_vars[@]} -ne 0 ]
then
    echo "The following variables are not set, but should be:" >&2
    printf ' %q\n' "${missing_vars[@]}" >&2
    exit 1
fi

मैं एक चर चर का उपयोग करता हूं जो चर सेट नहीं किया गया है, और उपयोगकर्ता-सामना संदेश लिखने के लिए परिणाम का उपयोग करें।

टिप्पणियाँ:

  • में उद्धृत ${required_vars[@]}कियाfor मुख्य रूप से आदत से बाहर लूप - मैं आपके चर नामों में किसी भी शेल मेटाचैकर्स को शामिल करने की सलाह नहीं दूंगा!
  • मैं बोली नहीं ${#missing_vars[@]} , क्योंकि यह हमेशा एक पूर्णांक है, भले ही आप पूर्ववर्ती सलाह की अवहेलना करने के लिए पर्याप्त विकृत हैं।
  • मैंने %qछपाई करते समय उपयोग किया ;%sसामान्य रूप से पर्याप्त होगा।
  • त्रुटि आउटपुट हमेशा त्रुटि स्ट्रीम में जाता है >&2 , इसलिए यह डाउनस्ट्रीम कमांड को पाइप नहीं करता है
  • मौन सुनहरा है - प्रगति की जानकारी या डिबगिंग जानकारी को प्रिंट न करें जब तक कि विशेष रूप से नहीं पूछा जाता है। यह त्रुटियों को और अधिक स्पष्ट करता है।

1

bash4.2 आपको यह परखने देता है कि क्या कोई चर -vऑपरेटर के साथ सेट किया गया है; एक परेशान चर और खाली स्ट्रिंग के लिए एक चर सेट दो अलग-अलग शर्तें हैं:

$ unset foo
$ [[ -v foo ]] && echo foo is set
$ [[ -z "$foo" ]] && echo foo is empty
foo is empty
$ foo=
$ [[ -v foo ]] && echo foo is set
foo is set
$ [[ -z "$foo" ]] && echo foo is empty
foo is empty

मैं "मल्टीपल" वैरिएबल के बारे में पूछ रहा था, इसलिए मैं इनडायरेक्शन जैसी किसी चीज की तलाश में था ...
जैस्पर

आप अविवेक की जरूरत नहीं है, के बाद से -vलेता है नाम एक चर के, इसलिए for var in one two three; [[ -v $var ]] && ...; doneमें से प्रत्येक अगर जाँच करेगा one, twoऔर threeअनुक्रम में स्थापित कर रहे हैं।
चेपनर

1

मुझे लगता है कि अगर आपका मतलब है not set, तो चर को कभी भी आरंभ नहीं किया जाना चाहिए। यदि आप उपयोग करते हैं [ -n "${!var}" ], तो जैसे खाली चर two=""विफल हो जाएगा, जबकि यह सेट है । आप यह कोशिश कर सकते हैं:

one=1
three=3

for var in one two three; do
  declare -p $var > /dev/null 2>&1 \
  && printf '%s is set to %s\n' "$var" "${!var}" \
  || printf '%s is not set\n' "$var"
done

0

एक संक्षिप्त (हालांकि थोड़ा हैसी) समाधान, मामले को संभालने के लिए जहां sourceडी स्क्रिप्ट के लिए चर को एक शून्य मान पर सेट करना ठीक है, स्क्रिप्ट को सोर्स करने से पहले कुछ विशेष मूल्य के लिए चर को इनिशियलाइज़ करना है, और उसके बाद उस मान के लिए जाँच करें , उदा

one=#UNSET#
two=#UNSET#
three=#UNSET#

. set_vars_script

if [[ $one$two$three == *#UNSET#* ]] ; then
  echo "One or more essential variables are unset" >&2
  exit 1
fi

1
एक और अच्छा समाधान है, लेकिन मैं एक और अधिक विशिष्ट त्रुटि संदेश देना चाहूंगा, तो "एक या एक से अधिक चर परेशान" ...
जस्पर

0

मैंने @ mikeserv का उत्तर बढ़ाया है ।

यह संस्करण उपस्थिति की जाँच करने के लिए चर की एक सूची लेता है, अनुपलब्ध चर का नाम मुद्रण और त्रुटि के लिए उपयोग () के लिए कॉल ट्रिगर करता है।

REQD_VALUES=("VARIABLE" "FOO" "BAR" "OTHER_VARIABLE")
( i=0; for var_name in ${REQD_VALUES[@]}; do
    VALUE=${!var_name} ;
    i=$((i+1)) ; : ${VALUE:?$var_name is missing}
done ) || usage

उदाहरण आउटपुट जब एक मान गायब है:

./myscript.sh: line 42: VALUE: OTHER_VARIABLE is missing

ध्यान दें कि आप VALUE नामक वैरिएबल को एक वैकल्पिक नाम में बदल सकते हैं जो आपके वांछित आउटपुट को बेहतर बनाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.