বাশ-এ অ্যারে খালি আছে কিনা তা পরীক্ষা করুন


110

আমার স্ক্রিপ্ট চলার সাথে সাথে আমার কাছে অ্যারে রয়েছে যা বিভিন্ন ত্রুটি বার্তায় পূর্ণ হয়ে যায়।

স্ক্রিপ্টের শেষে এটি ফাঁকা আছে কিনা তা যাচাই করার জন্য আমার একটি উপায় প্রয়োজন এবং এটি থাকলে একটি নির্দিষ্ট পদক্ষেপ নিতে হবে।

আমি এটি ইতিমধ্যে একটি সাধারণ ভিএআর এর মতো চিকিত্সা করার চেষ্টা করেছি এবং এটি পরীক্ষা করার জন্য -z ব্যবহার করেছিলাম, তবে এটি কার্যকর হবে বলে মনে হয় না। বাশে কোনও অ্যারে খালি আছে কিনা তা যাচাই করার কোনও উপায় আছে?

উত্তর:


143

ধরুন আপনার অ্যারেটি $errors, কেবলমাত্র উপাদানগুলির সংখ্যা শূন্য কিনা তা পরীক্ষা করে দেখুন।

if [ ${#errors[@]} -eq 0 ]; then
    echo "No errors, hooray"
else
    echo "Oops, something went wrong..."
fi

10
দয়া করে নোট করুন যে =এটি একটি স্ট্রিং অপারেটর। এটা তোলে এই ক্ষেত্রে সূক্ষ্ম কাজ ঘটবে, কিন্তু আমি সঠিক গাণিতিক অপারেটর ব্যবহার করতে চাই -eqপরিবর্তে (ধরো আমি স্যুইচ করতে চান চাই -geবা -lt, ইত্যাদি)।
মুসিফিল

6
এর সাথে কাজ করে না set -u: "আনবাউন্ড ভেরিয়েবল" - যদি অ্যারেটি খালি থাকে।
ইগোর

@ ইগর: বাশ ৪.৪-এ আমার জন্য কাজ করে। set -u; foo=(); [ ${#foo[@]} -eq 0 ] && echo empty। যদি আমি unset foo, তবে এটি মুদ্রণ করে তবে এটির চেয়ে foo: unbound variableআলাদা: অ্যারে ভেরিয়েবলটি বিদ্যমান এবং খালি থাকার পরিবর্তে অস্তিত্ব রাখে না।
পিটার

ব্যাশ ৩.২ (ওএসএক্স) ব্যবহার করার সময় এটিতেও পরীক্ষিত set -u- যতক্ষণ আপনি প্রথমে আপনার ভেরিয়েবলটি ঘোষণা করেছেন, এটি পুরোপুরি কার্যকর হয়।
জিরোমিম্পল

15

আমি সাধারণত এই ক্ষেত্রে গাণিতিক সম্প্রসারণ ব্যবহার করি:

if (( ${#a[@]} )); then
    echo not empty
fi

সুন্দর এবং পরিষ্কার! আমি এটা পছন্দ করি. আমি আরও নোট করেছি যে অ্যারের প্রথম উপাদানটি সর্বদা অস্থায়ী হয়, (( ${#a} ))(প্রথম উপাদানটির দৈর্ঘ্য) এছাড়াও কাজ করবে। তবে, এটি ব্যর্থ হবে a=(''), যেখানে (( ${#a[@]} ))উত্তর দেওয়া সফল হবে।
cxw

8

আপনি অ্যারেটিকে একটি সাধারণ ভেরিয়েবল হিসাবে বিবেচনা করতে পারেন। এইভাবে, কেবল ব্যবহার করে

if [ -z "$array" ]; then
    echo "Array empty"
else
    echo "Array non empty"
fi

বা অন্য দিক ব্যবহার করে

if [ -n "$array" ]; then
    echo "Array non empty"
else
    echo "Array empty"
fi

যে সমাধান সঙ্গে সমস্যা হল একটি অ্যারের ভালো ঘোষিত হয় যদি হয়: array=('' foo)। এই চেকগুলি অ্যারেটি খালি হিসাবে রিপোর্ট করবে, যদিও এটি পরিষ্কার নয়। (ধন্যবাদ @ মুশিফিল!)

ব্যবহার [ -z "$array[@]" ]সুস্পষ্টভাবেই কোনও সমাধান নয়। কোঁকড়া বন্ধনী উল্লেখ না $arrayকরা একটি স্ট্রিং হিসাবে ব্যাখ্যা করার চেষ্টা করে ( [@]সেই ক্ষেত্রে এটি একটি সাধারণ আক্ষরিক স্ট্রিং) এবং তাই সর্বদা মিথ্যা হিসাবে রিপোর্ট করা হয়: "আক্ষরিক স্ট্রিংটি [@]খালি?" স্পষ্টভাবে না।


7
[ -z "$array" ]বা [ -n "$array" ]কাজ করে না। চেষ্টা করুন array=('' foo); [ -z "$array" ] && echo empty, এবং এটি মুদ্রণ করবে emptyযদিও arrayপরিষ্কারভাবে খালি নয়।
মুসিফিল

2
[[ -n "${array[*]}" ]]পুরো অ্যারেটিকে স্ট্রিং হিসাবে বিভক্ত করে তোলে, যা আপনি শূন্য-অর দৈর্ঘ্যের জন্য পরীক্ষা করেন। আপনি যদি array=("" "")দুটি খালি উপাদান না রেখে শূন্য বলে মনে করেন, এটি কার্যকর হতে পারে।
পিটার কর্ডস

@ পিটারকর্ডস আমি মনে করি না এটি কার্যকর হয়। অভিব্যক্তিটি একটি একক স্থানের অক্ষরকে মূল্যায়ন করে এবং [[ -n " " ]]"সত্য", যা দুঃখের বিষয়। আপনার মন্তব্যটি হ'ল আমি যা করতে চাই
মাইকেল

@ মিশেল: ক্র্যাপ, আপনি ঠিক বলেছেন। এটি 2 টি উপাদান নয়, খালি স্ট্রিংয়ের 1-উপাদান অ্যারের সাথে কাজ করে। আমি এমনকি পুরানো বাশ পরীক্ষা করেছিলাম এবং এটি এখনও ভুল আছে; যেমন আপনি বলছেন set -xএটি কীভাবে প্রসারিত তা দেখায়। আমার ধারণা পোষ্ট করার আগে আমি সেই মন্তব্যটি পরীক্ষা করে দেখিনি। >। <আপনি এটিকে IFS=''(এই বিবৃতিটির চারপাশে সংরক্ষণ / পুনরুদ্ধার করুন) সেট করে এটি কাজ করতে পারেন , কারণ "${array[*]}"প্রসারণ আইএফএসের প্রথম চরিত্রের সাথে উপাদানগুলিকে পৃথক করে। (অথবা সেট না থাকলে স্থান)। তবে " যদি আইএফএসটি নাল হয় তবে পরামিতিগুলি বিভক্তকারীদের মধ্যবর্তী না করেই যুক্ত হয়ে যায় " "(position * অবস্থানিক প্যারামের জন্য ডকস, তবে আমি অ্যারেগুলির জন্যও একই ধারণা করি)।
পিটার কর্ডেস

@ মিশেল: একটি উত্তর যুক্ত করেছে যা এটি করে।
পিটার কর্ডেস

3

আমি এটি দিয়ে যাচাই করেছি bash-4.4.0:

#!/usr/bin/env bash
set -eu
check() {
    if [[ ${array[@]} ]]; then
        echo not empty
    else
        echo empty
    fi
}
check   # empty
array=(a b c d)
check   # not empty
array=()
check   # empty

এবং bash-4.1.5:

#!/usr/bin/env bash
set -eu
check() {
    if [[ ${array[@]:+${array[@]}} ]]; then
        echo non-empty
    else
        echo empty
    fi
}
check   # empty
array=(a b c d)
check   # not empty
array=()
check   # empty

পরবর্তী ক্ষেত্রে আপনার নিম্নলিখিত নির্মাণ প্রয়োজন:

${array[@]:+${array[@]}}

এটি খালি বা আনসেট বিন্যাসে ব্যর্থ না হওয়ার জন্য। আপনি যদি set -euআমার মতো করেন তবেই তা হয়। এটি আরও কঠোর ত্রুটি পরীক্ষার ব্যবস্থা করে provides দস্তাবেজগুলি থেকে :

-e

একটি পাইপলাইন (পাইপলাইন দেখুন) অবিলম্বে প্রস্থান করুন, যা কোনও একক সরল কমান্ড (সরল কমান্ডগুলি দেখুন), একটি তালিকা (তালিকা দেখুন), বা যৌগিক কমান্ড (যৌগিক কমান্ডগুলি দেখুন) একটি শূন্য-স্থিতি ফিরিয়ে দেয়। শেলটি প্রস্থান করে না যদি কমান্ডের ব্যর্থতা কমান্ড তালিকার সাথে সাথে কিছুক্ষণ পরে বা কীওয়ার্ড অবধি ব্যর্থ হয়, যদি একটি বিবৃতিতে পরীক্ষার অংশ হয়, কোনও && বা সম্পাদিত কোনও কমান্ডের অংশ || চূড়ান্ত && বা || অনুসরণকারী কমান্ড ব্যতীত, পাইপলাইনে থাকা কোনও কমান্ড শেষ না হলেও, বা যদি কমান্ডের ফেরতের স্থিতি উল্টানো হচ্ছে! যদি সাব-শেল ব্যতীত অন্য কোনও যৌগিক কমান্ড একটি শূন্য-স্থিতি প্রত্যাবর্তন করে কারণ একটি আদেশ কমান্ড ব্যর্থ হওয়ার সময় শেলটি প্রস্থান করে না। ERR এ একটি ফাঁদ সেট করা থাকলে শেলটি বেরোনোর ​​আগেই সম্পাদিত হয়।

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

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

-u

পরামিতি সম্প্রসারণের সময় বিশেষ পরামিতি '@' বা '*' ব্যতীত আনসেট ভেরিয়েবল এবং পরামিতিগুলি আচরণ করুন। স্ট্যান্ডার্ড ত্রুটিতে একটি ত্রুটি বার্তা লেখা হবে এবং একটি ইন্টারেক্টিভ শেলটি প্রস্থান করবে।

যদি আপনার এটির প্রয়োজন না হয় তবে :+${array[@]}অংশটি বাদ দিতে নির্দ্বিধায় ।

এছাড়াও খেয়াল করুন, [[অপারেটরটি এখানে ব্যবহার করা [আপনার কাছে প্রয়োজনীয়:

$ cat 1.sh
#!/usr/bin/env bash
set -eu
array=(a b c d)
if [ "${array[@]}" ]; then
    echo non-empty
else
    echo empty
fi

$ ./1.sh
_/1.sh: line 4: [: too many arguments
empty

আপনার সাথে -uঅবশ্যই ${array[@]+"${array[@]}"}সিএফ স্ট্যাকওভারফ্লো.com
a/34361807/

@ জাকুবচেনস্কি বাশের কোন সংস্করণের কথা বলছেন? gist.github.com/x-yuri/d933972a2f1c42a49fc7999b8d5c50b9
এক্স-

একক বন্ধনী উদাহরণে সমস্যাটি হ'ল @অবশ্যই। আপনি *অ্যারের সম্প্রসারণ যেমন ব্যবহার করতে পারেন [ "${array[*]}" ], আপনি না? তবুও, [[ভাল কাজ করে। একাধিক খালি স্ট্রিং সহ অ্যারের জন্য এই উভয়ের আচরণ কিছুটা আশ্চর্যজনক। উভয়ই [ ${#array[*]} ]এবং [[ "${array[@]}" ]]এটির জন্য মিথ্যা array=()এবং array=('')তবে সত্য array=('' '')(দুটি বা আরও খালি স্ট্রিং)। আপনি যদি সবার কাছে এক বা একাধিক খালি স্ট্রিং সত্য করতে চান তবে আপনি ব্যবহার করতে পারেন [ ${#array[@]} -gt 0 ]। আপনি যদি এগুলি সমস্ত মিথ্যা চাইতেন তবে আপনি তাদেরকে তাড়িয়ে দিতে //পারেন।

@ আইসড আমি ব্যবহার করতে পারতাম [ "${array[*]}" ], তবে যদি আমি এই জাতীয় অভিব্যক্তি চালিত করি তবে এটি কী করে তা বোঝা আমার পক্ষে আরও কঠিন। যেহেতু [...]ইন্টারপোলেশনের ফলে স্ট্রিংয়ের ক্ষেত্রে কাজ করে। এর বিপরীতে [[...]]যা কোনটি বিক্ষিপ্ত হয়েছিল তা সম্পর্কে সচেতন হতে পারে। যে, এটি এটি একটি অ্যারে পাস করা যেতে পারে যে জানতে পারেন। [[ ${array[@]} ]]আমার কাছে "অ্যারেটি খালি নয় কিনা তা পরীক্ষা করুন" হিসাবে পড়েন, যখন [ "${array[*]}" ]"সমস্ত অ্যারে উপাদানগুলির বিভাজনের ফলস্বরূপ একটি খালি নন স্ট্রিং হয় কিনা তা পরীক্ষা করে দেখুন"।
এক্স-ইউরি 15

... দুটি খালি স্ট্রিংয়ের সাথে আচরণ করা আমার পক্ষে মোটেও অবাক হওয়ার কিছু নয়। অবাক করা বিষয়টি হ'ল একটি খালি স্ট্রিংয়ের সাথে আচরণ। তবে যুক্তিযুক্ত যুক্তিযুক্ত। সম্পর্কিত [ ${#array[*]} ], আপনি সম্ভবত বোঝাতে চেয়েছিলেন [ "${array[*]}" ], যেহেতু পূর্ববর্তীটি কোনও সংখ্যক উপাদানের ক্ষেত্রে সত্য। কারণ উপাদানগুলির সংখ্যা সর্বদা খালি খালি স্ট্রিং থাকে। দুটি উপাদান সহ উত্তরোত্তর সম্পর্কে, বন্ধনীগুলির ভিতরে প্রকাশটি প্রসারিত হয় ' 'যা খালি খালি স্ট্রিং। হিসাবে [[ ${array[@]} ]], তারা কেবল ভাবেন (এবং ঠিক তাই) যে দুটি উপাদানের যে কোনও অ্যারে খালি নেই।
এক্স-ইউরি

2

আপনি যদি খালি উপাদানগুলির মতো কোনও অ্যারে সনাক্ত করতে চান তবে খালিarr=("" "") হিসাবে একইarr=()

আপনি সমস্ত উপাদান এক সাথে পেস্ট করতে পারেন এবং ফলাফলটি শূন্য-দৈর্ঘ্যের কিনা তা পরীক্ষা করতে পারেন। (অ্যারে বিষয়বস্তুগুলির একটি সমতল অনুলিপি নির্মাণের জন্য পারফরম্যান্সের জন্য আদর্শ নয় যদি অ্যারেটি খুব বড় হতে পারে তবে আশা করি আপনি সেই জাতীয় প্রোগ্রামের জন্য ব্যাশ ব্যবহার করছেন না ...)

কিন্তু "${arr[*]}"এর প্রথম চরিত্রের দ্বারা পৃথক উপাদানগুলির সাথে প্রসারিত হয় IFS। সুতরাং আপনাকে আইএফএস সংরক্ষণ / পুনরুদ্ধার করতে IFS=''হবে এবং এই কাজটি করতে হবে, অথবা অন্যথায় অ্যারে উপাদানগুলির স্ট্রিং দৈর্ঘ্য == # পরীক্ষা করুন - ১ ( nউপাদানগুলির একটি অ্যারেরে পৃথক রয়েছে n-1)। এই অফ বাই বাই মোকাবেলা করার জন্য, 1 দ্বারা সংক্ষিপ্তকরণ প্যাড করা সবচেয়ে সহজ

arr=("" "")

## Assuming default non-empty IFS
## TODO: also check for ${#arr[@]} -eq 0
concat="${arr[*]} "      # n-1 separators + 1 space + array elements
[[ "${#concat}" -ne "${#arr[@]}" ]]  && echo not empty array || echo empty array

পরীক্ষার ক্ষেত্রে set -x

### a non-empty element
$ arr=("" "x")
  + arr=("" "x")
$ concat="${arr[*]} ";  [[ "${#concat}" -ne "${#arr[@]}" ]] && echo not empty array || echo empty array
  + concat=' x '
  + [[ 3 -ne 2 ]]
  + echo not empty array
not empty array

### 2 empty elements
$ arr=("" "")
  + arr=("" "")
$ concat="${arr[*]} ";  [[ "${#concat}" -ne "${#arr[@]}" ]] && echo not empty array || echo empty array
  + concat='  '
  + [[ 2 -ne 2 ]]
  + echo empty array
empty array

দুর্ভাগ্যবশত, এই ব্যর্থ arr=(): [[ 1 -ne 0 ]] সুতরাং আপনাকে প্রথমে পৃথকভাবে খালি অ্যারেগুলি পরীক্ষা করতে হবে।


বা সাথেIFS='' । সম্ভবত আপনি সাবএসেল ব্যবহারের পরিবর্তে আইএফএস সংরক্ষণ / পুনরুদ্ধার করতে চান, কারণ আপনি সহজেই কোনও সাব-শেলের ফলাফল পেতে পারেন না।

# inside a () subshell so we don't modify our own IFS
(IFS='' ; [[ -n "${arr[*]}" ]] && echo not empty array || echo empty array)

উদাহরণ:

$ arr=("" "")
$ (IFS='' ; [[ -n "${arr[*]}" ]] && echo not empty array || echo empty array)
   + IFS=
   + [[ -n '' ]]
   + echo empty array
empty array

নেই এর সাথে কাজ arr=()- এটা এখনও ঠিক খালি স্ট্রিং আছে।


আমি উন্নত করেছি, তবে আমি ব্যবহার শুরু করেছি [[ "${arr[*]}" = *[![:space:]]* ]], যেহেতু আমি কমপক্ষে একটি নন-ডাব্লুএস চরিত্রের উপর নির্ভর করতে পারি।
মাইকেল

@ মিশেল: হ্যাঁ, আপনাকে যদি প্রত্যাখ্যান করার দরকার না হয় তবে এটি একটি ভাল বিকল্প arr=(" ")
পিটার কর্ডেস

0

আমার ক্ষেত্রে, দ্বিতীয় উত্তরটি যথেষ্ট ছিল না কারণ সেখানে শ্বেতস্থান থাকতে পারে। আমি সাথে এসেছি:

if [ "$(echo -ne ${opts} | wc -m)" -eq 0 ]; then
  echo "No options"
else
  echo "Options found"
fi

echo | wcশেল বিল্ট-ইনগুলি ব্যবহার করার তুলনায় অযথা অকার্যকর বলে মনে হচ্ছে।
পিটার কর্ডেস

নিশ্চিত না যে আমি @ পিটারকর্ডসকে বুঝতে পারলে, আমি কি দ্বিতীয় উত্তরগুলি ' [ ${#errors[@]} -eq 0 ];সাদা জায়গার সমস্যাটি ঘিরে কাজ করতে পারি? আমি অন্তর্নির্মিত পছন্দ করি।
মিশা

হোয়াইটস্পেস ঠিক কীভাবে সমস্যার সৃষ্টি করে? $#একটি সংখ্যা বিস্তৃতি, এবং পরেও কাজ করে জরিমানা opts+=("")। যেমন unset opts; opts+=("");opts+=(" "); echo "${#opts[@]}"আমি পেতে 2। আপনি কি এমন কিছু উদাহরণ ব্যবহার করতে পারেন যা কাজ করে না?
পিটার

অনেক দিন আগের কথা। আইআইআরসি উত্স উত্স সর্বদা কমপক্ষে "" মুদ্রিত হয়। সুতরাং, খালি নিউলাইন বা খালি স্ট্রিং উপেক্ষা করে opts = "" বা opts = ("") এর জন্য আমার 0 প্রয়োজন নয়, 1 প্রয়োজন।
মিশা 14

ঠিক আছে, তাই আপনি কি opts=("")হিসাবে একই আচরণ করা প্রয়োজন opts=()? এটি কোনও খালি অ্যারে নয়, তবে আপনি খালি অ্যারে বা খালি প্রথম উপাদানটি পরীক্ষা করে দেখতে পারেন opts=(""); [[ "${#opts[@]}" -eq 0 || -z "$opts" ]] && echo empty। মনে রাখবেন যে আপনার বর্তমান উত্তরটি "বিকল্প নেই" এর জন্য বলে opts=("" "-foo"), যা সম্পূর্ণ জাল এবং এটি আচরণের পুনরুত্পাদন করে। আপনি [[ -z "${opts[*]}" ]]অনুমান করতে পারেন, সমস্ত অ্যারের উপাদানগুলিকে একটি সমতল স্ট্রিংয়ের মধ্যে বিভক্ত করার -zজন্য , যা শূন্য-দৈর্ঘ্যের জন্য পরীক্ষা করে। যদি প্রথম উপাদানটি পরীক্ষা করা যথেষ্ট হয় তবে -z "$opts"কাজ করে।
পিটার কর্ডস

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