একাধিক ভেরিয়েবল সেট করা থাকলে পরীক্ষা করুন


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

তবে যদি দুটি সেট না করা থাকে তবে আমি এখনও "দুটি সেট করা হয় না" এর পরিবর্তে "two two to set" পাই।

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

আপডেট / সমাধান: আমি জানি যে "সেট" এবং "সেট, তবে ফাঁকা" এর মধ্যে পার্থক্য রয়েছে। আমি এখন ( /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

এটি কাজ করে, তবে / whitout quotes দিয়ে কি হচ্ছে? আমার সাধারণ পদ্ধতিটি কি প্রথম স্থানটি সঠিক?
জ্যাস্পার

হাঁ, যে precognitive: আমি প্রশ্নের উত্তর আগেই জিজ্ঞেস করা হয়েছিল ... 8-)
Hauke Laging

4
@ য্যাস্পার আপনার সর্বদা ভেরিয়েবল উদ্ধৃত করা উচিত । এটি প্রতিবার এটি প্রয়োজনীয় কিনা তা ভেবে বেশি সময় লাগবে না। তবে এটি ত্রুটিগুলি এড়িয়ে চলে।
হউক লেজিং

বিপরীতে, উদ্ধৃতি কেবল সম্প্রসারণের বিরুদ্ধে রক্ষা করে। আপনার যদি আগ্রহটি প্রসারিত হয় তবে উদ্ধৃতি দেওয়া অবশ্যই যাওয়ার উপায় নয়। উদাহরণস্বরূপ: সিএস = 673,290,765,; সেট - $ (আইএফএস =,; প্রতিধ্বনি $ সিএস); প্রতিধ্বনি $ #; আউটপুট: 3
মাইকজার্ভ

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

ফলাফল হবে

স্ক্রিপ্ট.শ: 3: স্ক্রিপ্ট.শ: ফু: প্যারামিটার সেট করা নেই

আপনি যদি এর bashপরিবর্তে ব্যবহার করেন তবে ত্রুটিটি দেখতে এইরকম হবে:

স্ক্রিপ্ট.শ: লাইন 3: ফু: আনবাউন্ড ভেরিয়েবল


এবং আপনার মতে এটি রান টাইম চেকগুলির জন্য কী বোঝায়?
হউক লেগেইজ

2
@ হককিজিং আমি আপনাকে পুরোপুরি অনুসরণ করি না - set -uওপি যে ধরণের ত্রুটি এড়াতে চাইছে তা প্রতিরোধ করে এবং (অন্যান্য সমস্ত সমাধানের বিপরীতে) নির্দিষ্ট ভেরিয়েবলগুলির মধ্যে সীমাবদ্ধ নয়। আসলে কোনও ভেরিয়েবলটি আনসেট করা অবস্থায় অপ্রত্যাশিত কাজ করার পরিবর্তে নিরাপদে ব্যর্থ হওয়া প্রায় সমস্ত শেল স্ক্রিপ্টগুলির জন্য এটি একটি কার্যকর সতর্কতা। এই নিবন্ধটি বিষয়টির একটি সহজ রেফারেন্স।
n.st

@ n.st আমি একমত নই - আপনি যদি এটির পরিকল্পনা করেন তবে নাল ঠিক ততটা কার্যকর হতে পারে।
মাইক্রোসার্ভ

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লুপ প্রধানত অভ্যাসের বাইরে - আমি তোমার পরিবর্তনশীল নামের যে কোন শেল metacharacters সহ উপদেশ না!
  • আমি উদ্ধৃতি দিলাম না ${#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

আমি @ মাইকজার্জারের উত্তরটি প্রসারিত করেছি ।

এই সংস্করণটি ভেরিয়েবলের উপস্থিতি যাচাই করতে, নিখোঁজ ভেরিয়েবলের নাম মুদ্রণ করতে এবং ত্রুটিতে ততক্ষণে ব্যবহারের কলটি ট্রিগার করতে ভেরিয়েবলের একটি তালিকা গ্রহণ করে।

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 নামক ভেরিয়েবলটিকে একটি বিকল্প নামে পরিবর্তন করতে পারেন যা আপনার পছন্দসই আউটপুটকে আরও ভাল মানায়।

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