শেল দ্বারা অ্যারে সমর্থন জন্য পরীক্ষা


12

কমান্ড লাইনে স্থানীয় বোর্নের মতো শেল দ্বারা অ্যারে সমর্থনের জন্য পরীক্ষার কোনও সংক্ষিপ্ত উপায় আছে?

এটি সর্বদা সম্ভব:

$ arr=(0 1 2 3);if [ "${arr[2]}" != 2 ];then echo "No array support";fi

বা $SHELLশেল সংস্করণের জন্য পরীক্ষা করা :

$ eval $(echo "$SHELL --version") | grep version

এবং তারপরে ম্যান পৃষ্ঠাটি পড়ে, ধরে নিয়েই আমার এতে অ্যাক্সেস রয়েছে। (এমনকি সেখানে থেকেও /bin/bash, আমি ধরে নিচ্ছি যে সমস্ত বোর্নের মতো শেলগুলি দীর্ঘ বিকল্পটি স্বীকার করে --version, যখন এটি উদাহরণস্বরূপ ksh এর জন্য বিরতি দেয় ))

আমি একটি সাধারণ পরীক্ষা খুঁজছি যা স্ক্রিপ্টের শুরুতে বা কল করার আগে এমনকি কোনও ব্যবহার বিভাগে অপ্রয়োজনীয় এবং সংযুক্ত করা যেতে পারে ।


আমি ধরে নিয়েছি আপনি বোর্নের মতো শেলগুলি সীমাবদ্ধ রাখতে চান?
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলাস: হ্যাঁ, আপনি যদি বোঝাতে (নিঃসন্দেহে নয়) মূল গ্রুপটি তৈরি করেন: sh, csh, ksh, tcsh, bash, zsh এবং ঘনিষ্ঠ বন্ধু। আমি জানি না যে এই নক্ষত্রমুখে যশ নিজে অবস্থান করছেন।
সিবিহে

2
cshকোনও বোর্ন শেল নয়। tcshএক নয় হয় (এটা cshকিছু বাগ সংশোধন করা হয়েছে সহ)
CA গুলির

1
নোটটি $SHELLহ'ল ব্যবহারকারীর $EDITORপছন্দসই শেল, যেমন তার পছন্দের পাঠ্য সম্পাদক। এটি বর্তমানে চলমান শেলটির সাথে সামান্যই সম্পর্কযুক্ত।
স্টাফেন চেজেলাস

1
eval$SHELL --versionশেল কোড হিসাবে আউটপুট uating বোঝা যায় না।
স্টাফেন চেজেলাস

উত্তর:


12

ধরে নেওয়া যাক আপনি বোর্ন মত শাঁস (অন্যান্য অনেক শাঁস পছন্দ করতে সীমাবদ্ধ করতে চান csh, tcsh, rc, esবা fishসমর্থন অ্যারে কিন্তু একটি স্ক্রিপ্ট শাঁস মত বোর্ন একই সময়ে সামঞ্জস্যপূর্ণ লেখা এবং সেই চতুর এবং সাধারণত অর্থহীন হিসাবে তারা সম্পূর্ণ ভিন্ন এবং জন্য দোভাষী হয় বেমানান ভাষা), নোট করুন যে বাস্তবায়নের মধ্যে উল্লেখযোগ্য পার্থক্য রয়েছে।

অ্যারে সমর্থন করে শাঁসের মতো বোর্ন হ'ল:

  • ksh88(এটিই প্রথম একের প্রয়োগকারী অ্যারে, ksh88 এখনও kshবেশিরভাগ traditionalতিহ্যবাহী বাণিজ্যিক ইউনিয়ন হিসাবে পাওয়া যায় যেখানে এটির ভিত্তিও রয়েছে sh)

    • অ্যারেগুলি এক-মাত্রিক
    • অ্যারেগুলি হিসাবে সংজ্ঞায়িত করা হয় set -A array foo barবা set -A array -- "$var" ...আপনি গ্যারান্টি দিতে না পারলে এটি $varএকটি -বা দিয়ে শুরু হবে না +
    • অ্যারে সূচকগুলি শুরু হয় 0
    • স্বতন্ত্র অ্যারে উপাদানগুলি হিসাবে নির্ধারিত হয় a[1]=value
    • অ্যারেগুলি বিরল। এটি সেট না করা a[5]=fooসত্ত্বেও কাজ করবে a[0,1,2,3,4]এবং এগুলি সেট না করে ছেড়ে দেবে।
    • ${a[5]}ইনডিস 5 এর এলিমেন্টটি অ্যাক্সেস করতে (অ্যারে কম ছড়িয়ে থাকলে the ষ্ঠ উপাদানটি অগত্যা নয়)। 5কোনো গাণিতিক এক্সপ্রেশন থাকতে পারে।
    • অ্যারের আকার এবং সাবস্ক্রিপ্ট সীমিত (4096)।
    • ${#a[@]} অ্যারেতে নির্ধারিত উপাদানগুলির সংখ্যা (বৃহত্তম নির্ধারিত সূচক নয়)।
    • নির্ধারিত সাবস্ক্রিপ্টগুলির তালিকা জানার উপায় নেই (পৃথকভাবে 4096 উপাদানগুলির পরীক্ষা করা ছাড়া [[ -n "${a[i]+set}" ]])।
    • $aহিসাবে একই ${a[0]}। এটি অ্যারেগুলি কোনও কোনওভাবে অতিরিক্ত মান প্রদান করে স্কেলার ভেরিয়েবলগুলি প্রসারিত করে।
  • pdkshএবং ডেরিভেটিভস (এটি বেশিরভাগ বিএসডি'র ভিত্তি kshএবং shksh93 উত্সটি মুক্ত করার আগে একমাত্র ওপেনসোর্স ksh বাস্তবায়ন ছিল):

    বেশিরভাগ ক্ষেত্রেই ksh88তবে নোট করুন:

    • কিছু পুরানো বাস্তবায়ন সমর্থন করে নি set -A array -- foo bar, (সেখানে --এটির দরকার ছিল না)।
    • ${#a[@]}সর্বশ্রেষ্ঠ নির্ধারিত ইনডিসের ইনডিস এক হয়। ( a[1000]=1; echo "${#a[@]}"অ্যারের আউটপুটস 1001 যদিও অ্যারেতে কেবল একটি উপাদান রয়েছে।
    • নতুন সংস্করণগুলিতে অ্যারের আকার আর সীমাবদ্ধ থাকবে না (পূর্ণসংখ্যার আকার ব্যতীত)।
    • সাম্প্রতিক সংস্করণ mkshথেকে অনুপ্রাণিত কিছু অতিরিক্ত অপারেটর bash, ksh93বা zshবরাদ্দকরণ মত একটি লা a=(x y), a+=(z), ${!a[@]}নিয়োগ সূচকের তালিকা জন্য।
  • zshzshঅ্যারেগুলি সাধারণত আরও ভালভাবে ডিজাইন করা হয় এবং সেরা kshএবং cshঅ্যারেগুলি গ্রহণ করে । এগুলির সাথে মিল রয়েছে kshতবে উল্লেখযোগ্য পার্থক্য রয়েছে:

    • সূচকগুলি 1 এ শুরু হয়, 0 নয় ( kshঅনুকরণ ব্যতীত ), যা বর্ন অ্যারে (অবস্থান পরামিতি $ @, যা zshএটির $ আরজিভি অ্যারে হিসাবেও প্রকাশ করে) এবং cshঅ্যারেগুলির সাথে সামঞ্জস্যপূর্ণ ।
    • এগুলি স্বাভাবিক / স্কেলার ভেরিয়েবল থেকে পৃথক প্রকারের। অপারেটরগুলি তাদের কাছে আলাদাভাবে প্রয়োগ হয় এবং আপনি সাধারণত আশা করতে চান d $aএর মতো ${a[0]}নয় তবে অ্যারের খালি উপাদানগুলিতে বিস্তৃত হয় ( "${a[@]}"সমস্ত উপাদানগুলির মতো ksh)।
    • এগুলি সাধারণ অ্যারে হয়, বিরল অ্যারে নয়। a[5]=1কাজ করে তবে 1 থেকে 4 অবধি সমস্ত উপাদানকে নির্ধারিত না করে যদি খালি স্ট্রিং দেয়। সুতরাং ${#a[@]}( ${#a}ksh এ যা ইন্ডিস 0 এর উপাদানের আকার হিসাবে একই ) অ্যারেতে থাকা উপাদানগুলির সংখ্যা এবং সর্বাধিক নির্ধারিত ইনডিস।
    • সহযোগী অ্যারে সমর্থিত।
    • অ্যারে নিয়ে কাজ করার জন্য প্রচুর পরিমাণে অপারেটর সমর্থিত, এখানে তালিকাভুক্ত নয়।
    • অ্যারে হিসাবে সংজ্ঞায়িত a=(x y)set -A a x yএছাড়াও কাজ করে set -A a -- x yতবে ksh এমুলেশন ( --zsh এমুলেশনে প্রয়োজন হয় না) না থাকলে সমর্থনযোগ্য নয়।
  • ksh93। (এখানে সর্বশেষ সংস্করণ বর্ণনা করা হয়)। ksh93, দীর্ঘ হিসাবে বিবেচিত পরীক্ষামূলক এখন আরও বেশি সংখ্যক সিস্টেমে পাওয়া যাবে যে এটি এফএসএস হিসাবে প্রকাশিত হয়েছে। উদাহরণস্বরূপ, এটি /bin/sh(যেখানে এটি বোর্ন শেলটি প্রতিস্থাপন করেছে /usr/xpg4/bin/sh, পসিক্স শেলটি এখনও ভিত্তিক রয়েছে ksh88) এবং kshএর Solaris 11। এর অ্যারেগুলি ksh88 এর প্রসারিত এবং উন্নত করে।

    • a=(x y)একটি অ্যারে সংজ্ঞায়িত করতে ব্যবহার করা যেতে পারে, তবে যেহেতু a=(...)যৌগিক ভেরিয়েবল ( a=(foo=bar bar=baz)) সংজ্ঞায়িত করতেও এটি ব্যবহৃত হয় , a=()এটি অস্পষ্ট এবং সংশ্লেষের ভেরিয়েবল ঘোষণা করে, অ্যারে নয়।
    • অ্যারেগুলি বহুমাত্রিক ( a=((0 1) (0 2))) এবং অ্যারের উপাদানগুলিও যৌগিক পরিবর্তনশীল ( a=((a b) (c=d d=f)); echo "${a[1].c}") হতে পারে ।
    • a=([2]=foo [5]=bar)একবারে বিরল অ্যারে সংজ্ঞায়িত করতে একটি বাক্য গঠন ব্যবহার করা যেতে পারে।
    • আকার সীমাবদ্ধতা সরানো।
    • সীমাতে নয় zsh, অ্যারে হেরফের করতে প্রচুর সংখ্যক অপারেটর সমর্থিত।
    • "${!a[@]}" অ্যারে সূচকগুলির তালিকা পুনরুদ্ধার করতে।
    • সহযোগী অ্যারেগুলি পৃথক প্রকার হিসাবেও সমর্থন করে।
  • bashbashজিএনইউ প্রকল্পের শেল। এটি shওএস / এক্স এর সাম্প্রতিক সংস্করণ এবং কিছু জিএনইউ / লিনাক্স বিতরণ হিসাবে ব্যবহৃত হয়েছে। bashঅ্যারে বেশিরভাগ ksh88বৈশিষ্ট্য ksh93এবং এর সাথে বেশিরভাগকে অনুকরণ করে zsh

    • a=(x y)সমর্থিত। সমর্থিত set -A a x y নয়a=()একটি খালি অ্যারে তৈরি করে (এতে কোনও যৌগিক ভেরিয়েবল নেই bash)।
    • "${!a[@]}" সূচকের তালিকার জন্য।
    • a=([foo]=bar)সিনট্যাক্স সমর্থিত পাশাপাশি ksh93এবং অন্যান্য কয়েকজন থেকে zsh
    • সাম্প্রতিক bashসংস্করণগুলি পৃথক প্রকার হিসাবে সাহসী অ্যারেগুলিকে সমর্থন করে।
  • yash। এটি তুলনামূলকভাবে সাম্প্রতিক, পরিষ্কার, মাল্টি-বাইট সচেতন POSIX sh বাস্তবায়ন। বিস্তৃত ব্যবহার হয় না। এর অ্যারেগুলির অনুরূপ আরও একটি পরিষ্কার এপিআইzsh

    • অ্যারে গুল্ম কম নয়
    • অ্যারে সূচকগুলি 1 থেকে শুরু হয়
    • সংজ্ঞায়িত (এবং ঘোষিত) সাথে a=(var value)
    • উপাদানগুলি arrayঅন্তর্নির্মিত sertedোকানো , মুছে ফেলা বা সংশোধিত
    • array -s a 5 value5 তম উপাদানটি সংশোধন করতে ব্যর্থ হবে যদি সেই উপাদানটি আগেই নির্ধারিত না করা হত।
    • অ্যারের উপাদানগুলির সংখ্যা হ'ল ${a[#]}, ${#a[@]}তালিকা হিসাবে উপাদানগুলির আকার।
    • অ্যারেগুলি আলাদা ধরণের। আপনার যা দরকার তা a=("$a")আগে আপনি যোগ করতে অথবা উপাদানের পরিবর্তন করতে পারেন একটি অ্যারের একটি স্কেলার পরিবর্তনশীল পুনরায় সংজ্ঞায়িত।
    • যখন অনুরোধ করা হয় তখন অ্যারেগুলি সমর্থন করে না sh

সুতরাং, সেখান থেকে আপনি অ্যারে সমর্থনের জন্য এটি সনাক্ত করতে পারেন, যা আপনি এটি করতে পারেন:

if (unset a; set -A a a; eval "a=(a b)"; eval '[ -n "${a[1]}" ]'
   ) > /dev/null 2>&1
then
  array_supported=true
else
  array_supported=false
fi

এই অ্যারেগুলি ব্যবহার করতে সক্ষম হওয়ার পক্ষে যথেষ্ট নয়। পুরো এবং স্বতন্ত্র উপাদান হিসাবে অ্যারে নির্ধারণের জন্য আপনাকে মোড়কের কমান্ডগুলি সংজ্ঞায়িত করতে হবে এবং আপনি স্পারেস অ্যারে তৈরির চেষ্টা করবেন না তা নিশ্চিত করে নিতে হবে।

মত

unset a
array_elements() { eval "REPLY=\"\${#$1[@]}\""; }
if (set -A a -- a) 2> /dev/null; then
  set -A a -- a b
  case ${a[0]}${a[1]} in
    --) set_array() { eval "shift; set -A $1"' "$@"'; }
        set_array_element() { eval "$1[1+(\$2)]=\$3"; }
        first_indice=0;;
     a) set_array() { eval "shift; set -A $1"' -- "$@"'; }
        set_array_element() { eval "$1[1+(\$2)]=\$3"; }
        first_indice=1;;
   --a) set_array() { eval "shift; set -A $1"' "$@"'; }
        set_array_element() { eval "$1[\$2]=\$3"; }
        first_indice=0;;
    ab) set_array() { eval "shift; set -A $1"' -- "$@"'; }
        set_array_element() { eval "$1[\$2]=\$3"; }
        first_indice=0;;
  esac
elif (eval 'a[5]=x') 2> /dev/null; then
  set_array() { eval "shift; $1=("'"$@")'; }
  set_array_element() { eval "$1[\$2]=\$3"; }
  first_indice=0
elif (eval 'a=(x) && array -s a 1 y && [ "${a[1]}" = y ]') 2> /dev/null; then
  set_array() { eval "shift; $1=("'"$@")'; }
  set_array_element() {
    eval "
      $1=(\${$1+\"\${$1[@]}"'"})
      while [ "$(($2))" -ge  "${'"$1"'[#]}" ]; do
        array -i "$1" "$2" ""
      done'
    array -s -- "$1" "$((1+$2))" "$3"
   }
  array_elements() { eval "REPLY=\${$1[#]}"; }
  first_indice=1
else
  echo >&2 "Array not supported"
fi

এবং তারপর আপনার সাথে অ্যারে উপাদানের অ্যাক্সেস "${a[$first_indice+n]}"সঙ্গে, পুরো তালিকা "${a[@]}"এবং মোড়কের ফাংশন ব্যবহার করুন ( array_elements, set_array, set_array_element) (মধ্যে একটি অ্যারের উপাদানের নম্বর পেতে $REPLY), একটি পুরো বা বরাদ্দ পৃথক উপাদান যেমন অ্যারে সেট।

সম্ভবত চেষ্টা মূল্য নয়। আমি ব্যবহার করতাম perlবোর্ন / POSIX শেল অ্যারে অথবা সীমা: "$@"

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

আপনি স্থানীয় স্কোপে (ফাংশন বা বেনামে ফাংশনগুলিতে) অ্যারের zshমতো হতে অ্যারেগুলিকে কনফিগার করতে পারেন ksh

myfunction() {
  [ -z "$ZSH_VERSION" ] || setopt localoption ksharrays
  # use arrays of indice 0 in this function
}

আপনি অনুকরণ করতে পারেন ksh( kshঅ্যারে এবং অন্যান্য বেশ কয়েকটি ক্ষেত্রে এর সাথে সামঞ্জস্যতা উন্নত করতে পারেন ):

myfunction() {
  [ -z "$ZSH_VERSION" ] || emulate -L ksh
  # ksh code more likely to work here
}

এটি মাথায় রেখে এবং আপনি yashএবং ডেরিভেটিভগুলির ksh88পুরানো সংস্করণগুলির জন্য সমর্থন ছেড়ে দিতে ইচ্ছুক এবং আপনি pdkshযতক্ষণ স্পারস অ্যারে তৈরি করার চেষ্টা করবেন না, ততক্ষণ আপনি ধারাবাহিকভাবে ব্যবহার করতে সক্ষম হবেন:

  • a[0]=foo
  • a=(foo bar)(তবে না a=())
  • "${a[#]}", "${a[@]}","${a[0]}"

সেই ফাংশনগুলিতে emulate -L ksh, যখন zshব্যবহারকারী এখনও তার অ্যারেগুলি সাধারণত zsh উপায়ে ব্যবহার করেন।


7

আপনি evalঅ্যারে সিনট্যাক্স ব্যবহার করে দেখতে পারেন :

is_array_support() (
  eval 'a=(1)'
) >/dev/null 2>&1

if is_array_support; then
  echo support
else
  echo not
fi

2
ksh88অ্যারে সমর্থন করে কিন্তু না a=()। ইন ksh93, a=()একটি যৌগিক ভেরিয়েবল ঘোষণা করে, অ্যারে না হলে ভ্যারিয়েবলটি আগে থেকে অ্যারে হিসাবে ঘোষণা না করা হয়।
স্টাফেন চ্যাজেলাস

2
এছাড়াও লক্ষ করুন যে অ্যারে বাস্তবায়নের মধ্যে উল্লেখযোগ্য পার্থক্য রয়েছে। উদাহরণস্বরূপ, কিছুতে অ্যারে সূচকগুলি 0 (বাশ, কেএসএস, কেএসএস অনুকরণে জেডএস) থেকে শুরু হয়, কারও কারও এক থেকে শুরু হয় (জেডএস, যশ)। কিছুগুলি সাধারণ অ্যারে / তালিকাগুলি, কিছুগুলি স্পার্স অ্যারে (সংযুক্তিযুক্ত অ্যারেগুলি যেমন কীএস বা বাশের মতো ধনাত্মক পূর্ণসংখ্যার মধ্যে সীমাবদ্ধ থাকে)।
স্টাফেন চেজেলাস

ইন yash, আপনি a[5]=1কিন্তু করবেন নাarray -s a 5 1
স্টাফেন চ্যাজেলাস

@ স্টাফেনচাজেলাস: নির্ভুলতার জন্য ধন্যবাদ। আমার ক্ষেত্রে অ্যারে (এসোসিয়েটিভ বা না) মোটামুটি সমর্থিত কিনা তাতেই সমস্ত কিছু ফোটে। ইনডেক্স-বেস সম্পর্কে বিশদ সহজেই কোনও স্ক্রিপ্টেও অনিয়ন্ত্রিতভাবে চালানো যেতে পারে।
সিবিহে

@ স্টাফেনচাজেলাস: যৌগিক পরিবর্তনশীলটি ksh93আমাকে অবাক করে দিয়েছিল, আপনি কি আমাকে এটি সম্পর্কে নথিপত্রের অংশ দেওয়ার বিষয়ে আপত্তি করবেন? আমি 1এটিতে কাজ করতে অ্যারে যুক্ত করছি।
cuonglm
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.