উপাদান বাশে অ্যারে থাকলে পরীক্ষা করুন


17

অ্যারে বাশতে কোনও উপাদান রয়েছে (এটি লুপিংয়ের চেয়ে ভাল) কিনা তা যাচাই করার একটি দুর্দান্ত উপায় আছে?

বিকল্পভাবে, একটি সংখ্যার বা স্ট্রিং পূর্বনির্ধারিত ধ্রুবকগুলির একটি সেটের সমান কিনা তা পরীক্ষা করার অন্য উপায় আছে কি?

উত্তর:


24

বাশ 4 এ, আপনি সহযোগী অ্যারে ব্যবহার করতে পারেন:

# set up array of constants
declare -A array
for constant in foo bar baz
do
    array[$constant]=1
done

# test for existence
test1="bar"
test2="xyzzy"

if [[ ${array[$test1]} ]]; then echo "Exists"; fi    # Exists
if [[ ${array[$test2]} ]]; then echo "Exists"; fi    # doesn't

প্রাথমিকভাবে অ্যারে সেট আপ করতে আপনি সরাসরি অ্যাসাইনমেন্টও করতে পারেন:

array[foo]=1
array[bar]=1
# etc.

বা এইভাবে:

array=([foo]=1 [bar]=1 [baz]=1)

প্রকৃতপক্ষে, মান [খালি] ক্ষেত্রে [[]] পরীক্ষাটি কাজ করে না। যেমন, "অ্যারে ['পরীক্ষা'] = ''"। এই ক্ষেত্রে, কী 'পরীক্ষা' উপস্থিত রয়েছে এবং আপনি এটি $ {! অ্যারে [@] with দিয়ে তালিকাভুক্ত দেখতে পাচ্ছেন, তবে "[[$ {অ্যারে ['পরীক্ষা']}]]; প্রতিধ্বনি $?" প্রতিধ্বনি 1, 0 নয়।
হরিদসভ

1
${array[$test1]}সহজ তবে সমস্যা রয়েছে: আপনি set -uযদি আপনার স্ক্রিপ্টগুলিতে (যা প্রস্তাবিত) ব্যবহার করেন তবে এটি কাজ করবে না , কারণ আপনি "আনবাউন্ড ভেরিয়েবল" পেয়ে যাবেন।
টোকল্যান্ড

@ টোকল্যান্ড: কে সুপারিশ করে? আমি অবশ্যই না।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

@ ডেনিসউইলিইমসন: ঠিক আছে, কিছু লোক এটির প্রস্তাব দেয়, তবে আমি মনে করি যে এই পতাকাগুলির মূল্য নির্বিশেষে একটি সমাধান করা ভাল লাগবে।
টোকল্যান্ড


10

এটি একটি পুরানো প্রশ্ন, কিন্তু আমি মনে করি কি সহজ সমাধান এখনো হাজির করেনি: test ${array[key]+_}। উদাহরণ:

declare -A xs=([a]=1 [b]="")
test ${xs[a]+_} && echo "a is set"
test ${xs[b]+_} && echo "b is set"
test ${xs[c]+_} && echo "c is set"

আউটপুট:

a is set
b is set

কিভাবে এই কাজ পরীক্ষা দেখার জন্য এই


2
তথ্য ম্যানুয়াল আপনাকে env"পরীক্ষা" নামটি গ্রহণ করে থাকতে পারে এমন অন্যান্য উপকরণ, অগ্রগতি এবং অন্যান্য ক্রিয়াকলাপগুলিতে অস্পষ্টতা এড়াতে আপনাকে পুনরায় স্মরণ করে। উপরে হিসাবে env test ${xs[a]+_} && echo "a is set"। আপনি ডাবল-বন্ধনী ব্যবহার করে এই কার্যকারিতাটিও পেতে পারেন, একই কৌশলটি পরে নাল পরীক্ষা করা:[[ ! -z "${xs[b]+_}" ]] && echo "b is set"
ড্যানিশচেউস্কি

এছাড়াও আপনি আরও সহজ[[ ${xs[b]+set} ]]
আর্ন এল।

5

যদি কোনও এসোসিয়েটিভ অ্যারের উপাদান উপস্থিত থাকে (সেট না করা) থাকে তা পরীক্ষা করার একটি উপায় রয়েছে, এটি খালি থেকে পৃথক:

isNotSet() {
    if [[ ! ${!1} && ${!1-_} ]]
    then
        return 1
    fi
}

তারপরে এটি ব্যবহার করুন:

declare -A assoc
KEY="key"
isNotSet assoc[${KEY}]
if [ $? -ne 0 ]
then
  echo "${KEY} is not set."
fi

কেবল একটি নোট: ঘোষণা করুন -এ ব্যাশ 3.2.39 (ডেবিয়ান লেনি) নিয়ে কাজ করে না, তবে এটি ব্যাশ ৪.১.৫ (ডিবিয়ান স্কিজে) -তে কাজ করে
পাউয়ে পোলেভিজ

সহযোগী অ্যারেগুলি বাশ 4
ডিয়েগো এফ ডুরন

1
নোট যে if ! some_check then return 1= some_check। তাই: isNotSet() { [[ ... ]] }। আমার সমাধানটি নীচে পরীক্ষা করুন, আপনি এটি একটি সাধারণ চেক করে করতে পারেন।
টোকল্যান্ড 25'12

3

অ্যারে বিষয়বস্তু গ্রেপ করে পাইপ করে কোনও প্রবেশিকা উপস্থিত রয়েছে কিনা তা আপনি দেখতে পাচ্ছেন।

 printf "%s\n" "${mydata[@]}" | grep "^${val}$"

আপনি গ্রেপ-এন এর সাথে একটি এন্ট্রির সূচকও পেতে পারেন, যা ম্যাচের লাইন নম্বর দেয় (শূন্য-ভিত্তিক সূচক পেতে 1 টি বিয়োগের কথা মনে রাখবেন) এটি খুব বড় অ্যারে বাদে যুক্তিসঙ্গত দ্রুত হবে।

# given the following data
mydata=(a b c "hello world")

for val in a c hello "hello world"
do
           # get line # of 1st matching entry
    ix=$( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 )

    if [[ -z $ix ]]
    then
        echo $val missing
    else
         # subtract 1.  Bash arrays are zero-based, but grep -n returns 1 for 1st line, not 0 
        echo $val found at $(( ix-1 ))
    fi
done

a found at 0
c found at 2
hello missing
hello world found at 3

ব্যাখ্যা:

  • $( ... ) কোনও ভেরিয়েবলের কমান্ডের আউটপুট ক্যাপচার করতে ব্যাকটিক্স ব্যবহার করা সমান
  • printf প্রতি লাইনে মাইডাটা এক উপাদান আউটপুট করে
  • (প্রয়োজনীয় সমস্ত উদ্ধৃতি, এর @পরিবর্তে *. "হ্যালো ওয়ার্ল্ড" কে 2 লাইনে বিভক্ত করা এড়ানো যায়)
  • grepসঠিক স্ট্রিংয়ের সন্ধান করে: ^এবং $শুরু এবং লাইনের শেষের সাথে মেলে
  • grep -n 4 টি আকারে লাইন প্রত্যাবর্তন করে: হ্যালো ওয়ার্ল্ড
  • grep -m 1 প্রথম ম্যাচটি সন্ধান করে
  • cut শুধু লাইন নম্বর নিষ্কাশন
  • প্রত্যাবর্তিত রেখা নম্বর থেকে 1 বিয়োগ করুন।

আপনি অবশ্যই বিয়োগফলটি কমান্ডে ভাঁজ করতে পারেন। তবে তারপরে -১ এর জন্য নিখোঁজ হওয়ার জন্য পরীক্ষা করুন:

ix=$(( $( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 ) - 1 ))

if [[ $ix == -1 ]]; then echo missing; else ... fi
  • $(( ... )) পূর্ণসংখ্যার গাণিতিক করে

1

আপনার মনে না হয় আপনি লুপিং না করে সঠিকভাবে এটি করতে পারবেন properly অ্যারে খুব সীমিত ডেটা ।

এখানে একটি সহজ বৈকল্পিক, এটি সঠিকভাবে বলবে যে "Super User"অ্যারে বিদ্যমান। কিন্তু এটি "uper Use"অ্যারের মধ্যেও বলবে ।

MyArray=('Super User' 'Stack Overflow' 'Server Fault' 'Jeff' );
FINDME="Super User"

FOUND=`echo ${MyArray[*]} | grep "$FINDME"`

if [ "${FOUND}" != "" ]; then
  echo Array contains: $FINDME
else
  echo $FINDME not found
fi

#
# If you where to add anchors < and > to the data it could work
# This would find "Super User" but not "uper Use"
#

MyArray2=('<Super User>' '<Stack Overflow>' '<Server Fault>' '<Jeff>' );

FOUND=`echo ${MyArray2[*]} | grep "<$FINDME>"`

if [ "${FOUND}" != "" ]; then
  echo Array contains: $FINDME
else
  echo $FINDME not found
fi

সমস্যাটি হ'ল অ্যারের মাধ্যমে লুপিংয়ের পাশাপাশি অ্যাঙ্করগুলি যুক্ত করার কোনও সহজ উপায় নেই (যা আমি ভাবতে পারি)। অ্যারে রাখার আগে আপনি এগুলিকে যোগ না করতে পারলে ...


ধ্রুবকগুলি বর্ণানুক্রমিক হলে এটি একটি দুর্দান্ত সমাধান (যদিও grep "\b$FINDME\b")। সম্ভবত অ-আলফানিউমারিক ধ্রুবকগুলির সাথে কোনও ফাঁকা স্থান নেই, দিয়ে কাজ "(^| )$FINDME(\$| )"করতে পারে (অথবা এর মতো কিছু ... আমি কখনই
রিজএক্সএক্স গ্রাপের

1
#!/bin/bash
function in_array {
  ARRAY=$2
  for e in ${ARRAY[*]}
  do
    if [[ "$e" == "$1" ]]
    then
      return 0
    fi
  done
  return 1
}

my_array=(Drupal Wordpress Joomla)
if in_array "Drupal" "${my_array[*]}"
  then
    echo "Found"
  else
    echo "Not found"
fi

1
আপনি কেন এই পদ্ধতির পরামর্শ দিচ্ছেন তা আপনি বিশদভাবে বলতে পারেন? ওপি জিজ্ঞাসা করেছিল অ্যারে দিয়ে লুপ না করে এটি করার কোনও উপায় আছে কিনা , যা আপনি করছেন in_array। চিয়ার্স
বেরিয়েব

ভাল, কমপক্ষে সেই লুপটি কোনও ফাংশনে ক্যাপসুল করা হয়েছে, যা অনেক ক্ষেত্রে (ছোট ডেটা সেট সহ) যথেষ্ট পরিমাণে ভাল হতে পারে এবং বাশ 4+ এর প্রয়োজন হয় না। সম্ভবত ${ARRAY[@]}ব্যবহার করা উচিত।
টোবিয়াস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.