কোন ইউনিক্স শেল স্ক্রিপ্টে পরিবেশের ভেরিয়েবল সেট করা আছে তা যাচাই করার জন্য একটি সংক্ষিপ্ত উপায় কী?


500

আমি কয়েকটি ইউনিক্স শেল স্ক্রিপ্ট পেয়েছি যেখানে আমার স্টাফ করা শুরু করার আগে নির্দিষ্ট পরিবেশের ভেরিয়েবলগুলি সেট করা আছে তা পরীক্ষা করা দরকার, তাই আমি এই ধরণের জিনিসটি করি:

if [ -z "$STATE" ]; then
    echo "Need to set STATE"
    exit 1
fi  

if [ -z "$DEST" ]; then
    echo "Need to set DEST"
    exit 1
fi

যা অনেক টাইপিং। পরিবেশের ভেরিয়েবলগুলির একটি সেট সেট করা আছে কিনা তা পরীক্ষা করার জন্য আরও কি মার্জিত আইডিয়ম আছে?

সম্পাদনা: আমার উল্লেখ করা উচিত যে এই ভেরিয়েবলগুলির কোনও অর্থপূর্ণ ডিফল্ট মান নেই - কোনও আনসেট না থাকলে স্ক্রিপ্টটি ত্রুটিযুক্ত হওয়া উচিত।


2
এই প্রশ্নের উত্তরের অনেকেরই মনে হয় আপনি কোড গল্ফ স্ট্যাক এক্সচেঞ্জে এমন কিছু দেখতে পাবেন ।
ড্যানিয়েল শিলিং

উত্তর:


587

প্যারামিটার সম্প্রসারণ

সুস্পষ্ট উত্তর হ'ল প্যারামিটার বিস্তারের বিশেষ ফর্মগুলির মধ্যে একটি ব্যবহার করা:

: ${STATE?"Need to set STATE"}
: ${DEST:?"Need to set DEST non-empty"}

বা, আরও ভাল (নীচে 'ডাবল উদ্ধৃতিগুলির অবস্থানের' বিভাগ দেখুন):

: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"

প্রথম রূপটি (কেবলমাত্র ব্যবহার করে ?) সেট করার জন্য স্টেট প্রয়োজন, তবে স্টেট = "" (একটি খালি স্ট্রিং) ঠিক আছে - আপনি যা চান ঠিক তা নয়, বিকল্প এবং পুরানো স্বরলিপি।

দ্বিতীয় বৈকল্পিক (ব্যবহার করে :?) এর জন্য DEST সেট করা এবং খালি নয়।

আপনি যদি কোনও বার্তা সরবরাহ না করেন তবে শেলটি একটি ডিফল্ট বার্তা সরবরাহ করে।

${var?}কনস্ট্রাক্ট সংস্করণ 7 ইউনিক্স এবং বোর্ন শেল (1978 বা এর কাছাকাছি) এর পোর্টেবল ফিরে। ${var:?}কনস্ট্রাক্ট সামান্য বেশি সাম্প্রতিক হল: আমার মনে হয় এটা 1981 প্রায় সিস্টেম তৃতীয় ইউনিক্স ছিল, কিন্তু এটা তার আগে PWB ইউনিক্স মধ্যে ছিল। এটি কার্ন শেল এবং বিশেষত বাশ সহ পসিক্স শেলগুলিতে।

এটি প্যারামিটার এক্সপেনশন নামে একটি বিভাগে শেলের ম্যান পৃষ্ঠাতে নথিভুক্ত হয় । উদাহরণস্বরূপ, bashম্যানুয়ালটি বলে:

${parameter:?word}

নাল বা আনসেট না হলে ডিসপ্লে ত্রুটি। যদি প্যারামিটারটি নাল বা আনসেট না হয় তবে শব্দের সম্প্রসারণ (বা শব্দটি উপস্থিত না থাকলে সেই প্রভাবের জন্য একটি বার্তা) স্ট্যান্ডার্ড ত্রুটি এবং শেলটিতে লেখা হয়, যদি এটি ইন্টারেক্টিভ না হয় তবে প্রস্থান করে। অন্যথায়, প্যারামিটারের মান প্রতিস্থাপিত হয়।

কর্নেল কমান্ড

আমার সম্ভবত যুক্ত করা উচিত যে কোলন কমান্ডটি কেবল তার যুক্তিগুলি মূল্যায়ন করে এবং তারপরে সফল হয়। এটি আসল শেল কমেন্টেশন স্বরলিপি ( #লাইনের শেষে ' ' এর আগে )। দীর্ঘদিন ধরে, বোর্ন শেল স্ক্রিপ্টগুলির প্রথম অক্ষর হিসাবে কোলন ছিল। সি শেল একটি স্ক্রিপ্ট পড়ে এবং প্রথম অক্ষরটি নির্ধারণ করতে ব্যবহৃত যে এটি শেল (একটি #'হ্যাশ) বা বোর্ন শেল (একটি' :'কোলন) এর জন্য ছিল কিনা তা নির্ধারণ করার জন্য । তারপরে কার্নেলটি এই অভিনেত্রীর সাথে যোগ দেয় এবং ' #!/path/to/program' এর জন্য সমর্থন যোগ করে এবং বোর্ন শেল'র #মন্তব্য পেয়ে যায় এবং কোলন কনভেনশনটি পথ ধরে যায়। তবে আপনি যদি কোনও স্ক্রিপ্ট জুড়ে এসেছেন যা কোলন দিয়ে শুরু হয়, তবে এখন আপনি কেন তা জানতে পারবেন।


ডাবল উদ্ধৃতি অবস্থান

ব্লং একটি মন্তব্যে জিজ্ঞাসা :

এই আলোচনা কোন চিন্তা? https://github.com/koalaman/shellcheck/issues/380#issuecomment-145872749

আলোচনার মূল বক্তব্য:

… যাইহোক, আমি যখন shellcheckএটি (0.4.1 সংস্করণ সহ) করব তখন আমি এই বার্তাটি পাই:

In script.sh line 13:
: ${FOO:?"The environment variable 'FOO' must be set and non-empty"}
  ^-- SC2086: Double quote to prevent globbing and word splitting.

এই ক্ষেত্রে আমার কী করা উচিত সে সম্পর্কে কোনও পরামর্শ?

সংক্ষিপ্ত উত্তরটি " shellcheckপরামর্শ অনুসারে করুন":

: "${STATE?Need to set STATE}"
: "${DEST:?Need to set DEST non-empty}"

কেন উদাহরণস্বরূপ, নিম্নলিখিত অধ্যয়ন করুন। নোট করুন যে :কমান্ডটি তার আর্গুমেন্টগুলি প্রতিধ্বনিত করে না (তবে শেলটি আর্গুমেন্টগুলি মূল্যায়ন করে)। আমরা যুক্তিগুলি দেখতে চাই, সুতরাং নীচের কোডটি তার printf "%s\n"জায়গায় ব্যবহার করে :

$ mkdir junk
$ cd junk
$ > abc
$ > def
$ > ghi
$ 
$ x="*"
$ printf "%s\n" ${x:?You must set x}    # Careless; not recommended
abc
def
ghi
$ unset x
$ printf "%s\n" ${x:?You must set x}    # Careless; not recommended
bash: x: You must set x
$ printf "%s\n" "${x:?You must set x}"  # Careful: should be used
bash: x: You must set x
$ x="*"
$ printf "%s\n" "${x:?You must set x}"  # Careful: should be used
*
$ printf "%s\n" ${x:?"You must set x"}  # Not quite careful enough
abc
def
ghi
$ x=
$ printf "%s\n" ${x:?"You must set x"}  # Not quite careful enough
bash: x: You must set x
$ unset x
$ printf "%s\n" ${x:?"You must set x"}  # Not quite careful enough
bash: x: You must set x
$ 

মানটি কীভাবে $xপ্রথমে প্রসারিত হবে *এবং তারপরে সামগ্রিক অভিব্যক্তি ডাবল উদ্ধৃতিতে না থাকলে ফাইলের নামের একটি তালিকা নোট করুন । এটি ঠিক করা shellcheckউচিত যা সুপারিশ করা হয়। আমি যাচাই করে দেখিনি যে যেখানে ফর্মটি ডাবল উদ্ধৃতিতে আবদ্ধ রয়েছে তাতে এটি আপত্তি করে না, তবে এটি যুক্তিযুক্ত অনুমান যে এটি ঠিক হবে।


2
এটাই আমার দরকার। আমি 1987 সাল থেকে ইউনিক্সের বিভিন্ন সংস্করণ ব্যবহার করে আসছি এবং আমি এই সিনট্যাক্সটি কখনই দেখিনি - কেবল দেখাতে
চলেছে

এটি কীভাবে কাজ করে এবং কোথায় এটি ডকুমেন্টেড হয়? আমি ভাবছি এটি পরিবর্তনশীল বিদ্যমান এবং এটি একটি নির্দিষ্ট মান সেট করা হয়েছে তা পরীক্ষা করার জন্য এটি পরিবর্তন করা যেতে পারে।
jhabbott

6
এটি শেল ম্যানুয়াল পৃষ্ঠায় নথিবদ্ধ হয় বা বাশ ম্যানুয়াল সাধারণত শিরোনাম 'প্যারামিটার এক্সপেনশন' এর অধীনে। আদর্শ উপায় চেক করতে পরিবর্তনশীল বিদ্যমান কিনা একটি নির্দিষ্ট মানে সেট করা (বলুন 'ABC') কেবল হল: if [ "$variable" = "abc" ]; then : OK; else : variable is not set correctly; fi
জোনাথন লেফলার

আমি এই সিনট্যাক্সটি কীভাবে ফাঁকা স্থানের স্ট্রিং ভেরিয়েবল সহ ব্যবহার করব। "এই: কমান্ডটি পাওয়া যায় নি" বলে আমি একটি ত্রুটি পেয়েছি যখন আমি ভেরিয়েবলটি সেট করি আমি "এটি একটি পরীক্ষা" পরীক্ষা করতে চাই। কোন ধারনা?
ব্যবহারকারী 2294382

1
এই আলোচনা কোন চিন্তা? github.com/koalaman/shellcheck/issues/…
blong

138

এটা চেষ্টা কর:

[ -z "$STATE" ] && echo "Need to set STATE" && exit 1;

8
এটা বরং ভার্জোজ। আধা-কোলন অপ্রয়োজনীয়।
জোনাথন লেফলার

3
বা এমন কি খাটো [ -z "$STATE" ] && { echo "Need to set STATE"; exit 1; } দেখতে এই ব্লগ পোস্টে
zipizap

36
যেটি, তা পঠনযোগ্য। আমি এই সব জন্য। ব্যাশ স্ক্রিপ্টগুলির যে বিভাগে তারা পেতে পারে তার সমস্ত সহায়তা দরকার!
আয়ান ডানকান

মূল উত্তরটি এর বাক্য গঠনে আরও সুসংগত।
দ্রুত দাঁত

4
এটি যাইহোক, একটি আনসেট ভেরিয়েবল এবং খালি স্ট্রিংয়ের একটি ভেরিয়েবল সেটের মধ্যে পার্থক্য করে না।
চিপনার

57

আপনার প্রশ্ন আপনি যে শেলটি ব্যবহার করছেন তার উপর নির্ভরশীল।

বোর্ন শেল আপনার পরে যা চলছে তার পথে খুব কম পাতা ফেলে leaves

কিন্তু ...

এটি প্রায় সব জায়গায় কাজ করে।

শুধু চেষ্টা করুন এবং csh থেকে দূরে থাকুন। বর্ন শেলটির তুলনায় এটি ঘণ্টা এবং শিসগুলি যুক্ত করার জন্য ভাল ছিল, তবে এটি এখন সত্যই তৈরি হচ্ছে। আপনি যদি আমাকে বিশ্বাস না করেন, তবে চেষ্টা করুন এবং সিএসএসে এসটিডিআরআর আলাদা করুন! (-:

এখানে দুই সম্ভাবনা আছে। উপরোক্ত উদাহরণ, যথা:

${MyVariable:=SomeDefault}

প্রথমবারের জন্য আপনাকে $ MyVariable উল্লেখ করতে হবে। এই env লাগে। var MyVariable এবং যদি এটি বর্তমানে সেট না করা থাকে তবে সামনেরডিফল্টের মান পরবর্তী ব্যবহারের জন্য ভেরিয়েবলের জন্য বরাদ্দ করে।

আপনারও এর সম্ভাবনা রয়েছে:

${MyVariable:-SomeDefault}

আপনি কেবল যেখানে এই নির্মাণটি ব্যবহার করছেন সেখানে ভেরিয়েবলের জন্য স্যামডেফল্টকে পরিবর্তিত করে। এটি ভেরিয়েবলের জন্য সামুদ্রাফল্টকে মূল্য বরাদ্দ করে না এবং এই বিবৃতিটি আসার পরে মাইভ্যারিয়েবলের মানটি শূন্য হবে।


3
সিএসএইচ: (foo> foo.out)> & foo.err
মিঃআর

বোর্ন শেল যা প্রয়োজন তা করে।
জোনাথন লেফলার

51

নিশ্চয়ই সহজ পদ্ধিতিটি হ'ল -uআপনি ব্যবহার করছেন ধরে ধরে শেবাং (আপনার স্ক্রিপ্টের শীর্ষে লাইন) এ স্যুইচ যুক্ত করুন bash:

#!/bin/sh -u

এর ফলে যদি কোনও আনবাউন্ড ভেরিয়েবল লুকিয়ে থাকে তবে স্ক্রিপ্টটি প্রস্থান করবে।


40
${MyVariable:=SomeDefault}

যদি MyVariableসেট করা থাকে এবং শূন্য না হয় তবে এটি পরিবর্তনশীল মানটি পুনরায় সেট করবে (= কিছুই হবে না)।
অন্য, MyVariableসেট করা আছে SomeDefault

উপরেরগুলি কার্যকর করার চেষ্টা করবে ${MyVariable}, সুতরাং আপনি যদি ভেরিয়েবলটি সেট করতে চান তবে:

MyVariable=${MyVariable:=SomeDefault}

এটি বার্তাটি উত্পন্ন করে না - এবং প্রশ্নটি বলে যে কোনও ডিফল্ট নেই (যদিও আপনি নিজের উত্তর টাইপ করার সময় এটি বলেন নি)।
জোনাথন লেফলার

10
সঠিক সংস্করণগুলি: (1): $ {মাইভেরিয়েবল: = সোমডেফাল্ট} বা (2): মাইভ্যারেবল = $ {মাইভেরিয়েবল: -সোমডেফল্ট}
জোনাথন লেফলার

23

আমার মতে #! / বিন / এস এর জন্য সবচেয়ে সহজ এবং সর্বাধিক সামঞ্জস্যপূর্ণ চেকটি হ'ল:

if [ "$MYVAR" = "" ]
then
   echo "Does not exist"
else
   echo "Exists"
fi

আবার এটি / বিন / শ এর জন্য এবং এটি পুরানো সোলারিস সিস্টেমেও উপযুক্ত।


এই 'কাজ', কিন্তু পুরাতন সোলারিস সিস্টেমে আছে /bin/shসমর্থন ${var:?}স্বরলিপি, ইত্যাদি
জনাথন Leffler

এখন পর্যন্ত সেরা উত্তর।
ওলে

4
খালি স্ট্রিংয়ে সেট করা মোটেও সেট না করা থেকে আলাদা। এই পরীক্ষাটি প্রিন্ট উভয় পরে "নেই কোন অস্তিত্ব নেই করবে" unset MYVARএবং MYVAR=
চিপনার

@ চেপনার, আমি সম্ভবত আপনার মূল্যবান মূল্যবান মাথাব্যথার জন্য মন্তব্যটি উত্সাহিত করেছি, কিন্তু তারপরে আমি এটি পরীক্ষা করে (বাশ দিয়ে) গিয়েছিলাম এবং এটি সেট না করেই খালি স্ট্রিংয়ের জন্য কোনও ভার সেট করতে পারিনি। আপনি এটা কিভাবে করবেন?
জেড

@ এসজেড আমি নিশ্চিত আপনি কি বলতে চাইছেন তা নিশ্চিত নই। "আনসেট" অর্থ নামটির নির্ধারিত কোনও মূল্য নেই। যদি fooসেট না করা থাকে, "$foo"তবুও খালি স্ট্রিংয়ে প্রসারিত হয়।
চিপনার

17

bash4.2 চালু -vঅপারেটর যা একটি নাম সেট করা হয় যদি পরীক্ষা কোন মান, এমনকি খালি স্ট্রিং।

$ unset a
$ b=
$ c=
$ [[ -v a ]] && echo "a is set"
$ [[ -v b ]] && echo "b is set"
b is set
$ [[ -v c ]] && echo "c is set"
c is set

16

আমি সর্বদা ব্যবহৃত:

if [ "x$STATE" == "x" ]; then echo "Need to set State"; exit 1; fi

এর চেয়ে বেশি সংক্ষিপ্ত নয়, আমি ভয় করি।

সিএসএইচের অধীনে আপনার $? রাজ্য রয়েছে?


2
STATEখালি বা আনসেট করা আছে কিনা তা পরীক্ষা করে , কেবল সেট না করে সেট করুন।
চিপনার

7

আমার মতো ভবিষ্যতের লোকের জন্য, আমি এক ধাপ এগিয়ে যেতে এবং বর্ণের নামটি প্যারামিটারাইজ করতে চেয়েছিলাম, তাই আমি পরিবর্তনশীল নামের একটি পরিবর্তনশীল আকারের তালিকাটি লুপ করতে পারি:

#!/bin/bash
declare -a vars=(NAME GITLAB_URL GITLAB_TOKEN)

for var_name in "${vars[@]}"
do
  if [ -z "$(eval "echo \$$var_name")" ]; then
    echo "Missing environment variable $var_name"
    exit 1
  fi
done

3

আমরা একবারে ভেরিয়েবলগুলির একগুচ্ছ পরীক্ষা করার জন্য একটি দুর্দান্ত দৃ write়তা লিখতে পারি:

#
# assert if variables are set (to a non-empty string)
# if any variable is not set, exit 1 (when -f option is set) or return 1 otherwise
#
# Usage: assert_var_not_null [-f] variable ...
#
function assert_var_not_null() {
  local fatal var num_null=0
  [[ "$1" = "-f" ]] && { shift; fatal=1; }
  for var in "$@"; do
    [[ -z "${!var}" ]] &&
      printf '%s\n' "Variable '$var' not set" >&2 &&
      ((num_null++))
  done

  if ((num_null > 0)); then
    [[ "$fatal" ]] && exit 1
    return 1
  fi
  return 0
}

নমুনা প্রার্থনা:

one=1 two=2
assert_var_not_null one two
echo test 1: return_code=$?
assert_var_not_null one two three
echo test 2: return_code=$?
assert_var_not_null -f one two three
echo test 3: return_code=$? # this code shouldn't execute

আউটপুট:

test 1: return_code=0
Variable 'three' not set
test 2: return_code=1
Variable 'three' not set

এ জাতীয় আরও বক্তব্য এখানে: https://github.com/codefirester/base/blob/master/lib/assertions.sh



1

উপরের সমাধানগুলির কোনওটিই আমার উদ্দেশ্যগুলির জন্য কাজ করেনি, অংশ হিসাবে আমি একটি দীর্ঘ প্রক্রিয়া শুরু করার আগে সেট করতে হবে এমন ভেরিয়েবলগুলির একটি ওপেন-এন্ডেড তালিকার জন্য পরিবেশটি পরীক্ষা করছি। আমি এটি দিয়ে শেষ করেছি:

mapfile -t arr < variables.txt

EXITCODE=0

for i in "${arr[@]}"
do
   ISSET=$(env | grep ^${i}= | wc -l)
   if [ "${ISSET}" = "0" ];
   then
      EXITCODE=-1
      echo "ENV variable $i is required."
   fi
done

exit ${EXITCODE}

-1

বাহ্যিক শেল স্ক্রিপ্টগুলি ব্যবহার করার পরিবর্তে আমি আমার লগইন শেলটিতে ফাংশন লোড করার প্রবণতা রাখি। আমি কোনও সেট ভেরিয়েবলের চেয়ে পরিবেশের ভেরিয়েবলগুলি পরীক্ষা করতে সহায়ক ফাংশন হিসাবে এর মতো কিছু ব্যবহার করি:

is_this_an_env_variable ()
    local var="$1"
    if env |grep -q "^$var"; then
       return 0
    else
       return 1
    fi
 }

1
এটা ভুল. is_this_an_env_variable Pসাফল্য ফিরে আসবে কারণ PATHবিদ্যমান।
এরিক

এটি পরিবেশগত পরিবর্তনশীল কারণ এটি বিদ্যমান। এটি একাউল ননল স্ট্রিং সেট করা হয়েছে কিনা তা অন্য বিষয়।
নাফদেফ

-7

$?সিনট্যাক্স বেশ ঝরঝরে হল:

if [ $?BLAH == 1 ]; then 
    echo "Exists"; 
else 
    echo "Does not exist"; 
fi

এটি কাজ করে, তবে এখানে কি কেউ জানেন যে আমি সেই বাক্য গঠনে ডক্সটি কোথায় খুঁজে পাব? $? সাধারণত পূর্ববর্তী রিটার্ন মান।
ড্যানি স্ট্যাপল

আমার খারাপ - এটি কাজ করে না। একটি সহজ স্ক্রিপ্টে চেষ্টা করুন, সেটটি ছাড়াই এবং ছাড়াই।
ড্যানি স্ট্যাপল

11
বোর্নে, কর্ন, বাশ এবং পসিক্স শেলগুলি $?হল পূর্ববর্তী কমান্ডের প্রস্থান স্থিতি; $?BLAHপূর্ববর্তী কমান্ডের প্রস্থান স্থিতি 'BLAH' দিয়ে সংযুক্ত স্ট্রিং। এটি ভেরিয়েবলটি মোটেও পরীক্ষা করে না $BLAH। (এখানে একটি গুজব রয়েছে যা এটি প্রয়োজনে কমবেশি করতে পারে cshতবে সমুদ্রের শেলগুলি সমুদ্রের তীরে
ভালভাবেই

যতদূর বাশ সম্পর্কিত এটি সম্পূর্ণ ভুল উত্তর।
কোডফোরস্টার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.