ব্যাশে পরামিতি হিসাবে অ্যারে পাস করা Pass


188

আমি কীভাবে কোনও ব্যাশ ফাংশনে প্যারামিটার হিসাবে একটি অ্যারে পাস করতে পারি?

দ্রষ্টব্য: স্ট্যাক ওভারফ্লোতে এখানে কোনও উত্তর না পাওয়ার পরে আমি আমার কিছুটা অপরিশোধিত সমাধান নিজে পোস্ট করেছি। এটি কেবলমাত্র একটি অ্যারে পাস করার অনুমতি দেয় এবং এটি প্যারামিটার তালিকার শেষ উপাদান। প্রকৃতপক্ষে, এটি বিন্যাসটি মোটেও পাস করছে না, তবে এর উপাদানগুলির একটি তালিকা, যা __ ফাংশন () নামে একটি অ্যারেতে পুনরায় একত্রিত হয়, তবে এটি আমার পক্ষে কাজ করে। যদি কেউ আরও ভাল উপায় জানেন তবে এটিকে এখানে নির্বিঘ্নে যোগ করুন।


1
এখানে আপনার কাছে দুর্দান্ত রেফারেন্স এবং প্রচুর উদাহরণ রয়েছে।
আর্টেম বার্জার

16
এরর ... একই মিনিটের মধ্যে পাঁচ বছরের পুরানো প্রশ্নে তিনটি ডাউনভোট?
দেবসোলার

উত্তর:


219

আপনি এরকম কিছু ব্যবহার করে আর্গুমেন্ট হিসাবে একাধিক অ্যারে পাস করতে পারেন:

takes_ary_as_arg()
{
    declare -a argAry1=("${!1}")
    echo "${argAry1[@]}"

    declare -a argAry2=("${!2}")
    echo "${argAry2[@]}"
}
try_with_local_arys()
{
    # array variables could have local scope
    local descTable=(
        "sli4-iread"
        "sli4-iwrite"
        "sli3-iread"
        "sli3-iwrite"
    )
    local optsTable=(
        "--msix  --iread"
        "--msix  --iwrite"
        "--msi   --iread"
        "--msi   --iwrite"
    )
    takes_ary_as_arg descTable[@] optsTable[@]
}
try_with_local_arys

প্রতিধ্বনিত হবে:

sli4-iread sli4-iwrite sli3-iread sli3-iwrite  
--msix  --iread --msix  --iwrite --msi   --iread --msi   --iwrite

সম্পাদনা / নোট: (নীচের মন্তব্য থেকে)

  • descTableএবং optsTableনাম হিসাবে পাস এবং ফাংশন প্রসারিত হয়। $পরামিতি হিসাবে দেওয়া হয় সুতরাং কোন প্রয়োজন হয়।
  • নোট করুন যে এটি এখনও descTableসংজ্ঞায়িত করা ইত্যাদির সাথেও কাজ করে local, কারণ স্থানীয়রা তাদের কল করা ফাংশনগুলিতে দৃশ্যমান।
  • !মধ্যে ${!1}ARG 1 পরিবর্তনশীল বিস্তৃতি ঘটে।
  • declare -a কেবল সূচকযুক্ত অ্যারেটিকে সুস্পষ্ট করে তোলে, এটি কঠোরভাবে প্রয়োজন হয় না।

14
একটি বিষয় লক্ষণীয় হ'ল যদি মূল অ্যারেটি খুব কম হয় তবে প্রাপ্তি কার্যের অ্যারেতে একই সূচক থাকবে না।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

13
এটি দুর্দান্ত, 2 - "টেকস ..." এর প্রথম লাইনে কেন একটি সুস্পষ্ট অ্যারে ঘোষণা প্রয়োজন? 3 - এবং কি করে! expression {! 1 expression অভিব্যক্তিটির অর্থ এবং কেন [@] সেখানে প্রয়োজনীয় বা এমনকি অনুমতিপ্রাপ্ত নয় কেন? - এটি কাজ করে, এবং এই সমস্ত বিবরণ আমার পরীক্ষার ভিত্তিতে প্রয়োজন বলে মনে হচ্ছে তবে আমি বুঝতে চাই কেন!
জান হেটিচ

8
1: descTable এবং optsTable কেবল নাম হিসাবে পাস করা হয়, সুতরাং কোনও no নেই, সেগুলি কেবল তথাকথিত ফাংশন 2-তে প্রসারিত হবে: সম্পূর্ণ নিশ্চিত নয়, তবে আমি মনে করি এটি সত্যিই প্রয়োজনীয় নয় 3: the! ব্যবহৃত হয় কারণ ফাংশনে পাস হওয়া প্যারামিটারগুলি দু'বার প্রসারিত করা দরকার: $ 1 "descTable [@]" এ প্রসারিত হয় এবং এটি "$ {descTable [@]}" এ প্রসারিত হওয়া উচিত। } {! 1} সিনট্যাক্সটি এটি করে।
এলমার জান্ডার

8
আমি মনে করি না "ঘোষিত -a" অংশটি প্রয়োজনীয়। প্রথম বন্ধনের অস্তিত্ব ইতিমধ্যে একটি অ্যারের হিসাবে অ্যাসাইনমেন্টের এলএইচএসকে সংজ্ঞায়িত করে।
এরিক অ্যারোনস্টি

3
এই উত্তরটি আমাকে এখনই একটি সমস্যা সমাধানে সহায়তা করেছে। তবে, আমি এটি চিহ্নিত করতে চেয়েছিলাম যে আমার মেশিনে (ব্যাশ ৪.৩.৪২ ব্যবহার করে) "$ {! 1}" এবং "$ {! 2}" এর উদ্ধৃতিগুলি সরানো দরকার। যদি আপনি এটি না করেন তবে মূল অ্যারের মানটি একটি স্ট্রিং হিসাবে পড়ে এবং যথাক্রমে argAry1 [0] এবং argAry2 [0] এ নির্ধারিত হয়, মূলত অ্যারে কাঠামোটি হারিয়ে গেছে meaning
ব্যবহারকারীর সাথে বন্ধুত্বপূর্ণ

85

দ্রষ্টব্য: স্ট্যাক ওভারফ্লোতে এখানে কোনও উত্তর না পাওয়ার পরে আমি নিজেই পোস্ট করা কিছুটা অশোধিত সমাধান। এটি কেবলমাত্র একটি অ্যারে পাস করার অনুমতি দেয় এবং এটি প্যারামিটার তালিকার শেষ উপাদান। প্রকৃতপক্ষে, এটি বিন্যাসটি মোটেও পাস করছে না, তবে এর উপাদানগুলির একটি তালিকা, যা __ ফাংশন () নামে একটি অ্যারেতে পুনরায় একত্রিত হয়, তবে এটি আমার পক্ষে কাজ করে। কিছুটা পরে কেন তার সমাধান পোস্ট করেছে, তবে আমি এখানে "historicতিহাসিক" রেফারেন্সের জন্য আমার রেখেছি।

calling_function()
{
    variable="a"
    array=( "x", "y", "z" )
    called_function "${variable}" "${array[@]}"
}

called_function()
{
    local_variable="${1}"
    shift
    local_array=("${@}")
}

TheBonsai দ্বারা উন্নত, ধন্যবাদ।


19
সত্যের তিন বছর পরে, এই উত্তরটি - কেবল historicalতিহাসিক কারণে রাখা হয়েছিল - কয়েক দিনের মধ্যে দুটি ডাউনভোট পেয়েছে। দুঃখজনকভাবে এসও তেমন স্বাভাবিক, লোকেরা কেন এটি সুশৃঙ্খল বলে মনে করে তা নিয়ে কোনও নোট ছাড়াই। নোট এই উত্তরটি যে চেয়েও পুরনো সেই বৃক্ষকে করেছি স্মরণিকা এবং আমি সবচেয়ে ভালো সমাধান হিসেবে কেন এর উত্তর গৃহীত হয়। আমি নিখুঁতভাবে অবগত যে এটি কোথাও নিখুঁত কাছাকাছি নয়, তবে চার মাসের জন্য এটি এসওতে সেরা উপলব্ধ ছিল। কেন এটা দুই downvoted হবে বছর পরে এটি কেন এর নির্ভুল সমাধান দ্বিতীয় স্থান গ্রহণ আমাকে পরলোক হল।
দেবসোলার

@ গিরিহা: আমি আপনাকে জিজ্ঞাসা করব যে প্রশ্নটি কে পোস্ট করেছেন, কে এই উত্তর পোস্ট করেছেন এবং কে সম্ভবত উত্তরটি গ্রহণ করেছেন আপনি "খারাপ" বলছেন। ;-) এছাড়াও আপনি চেক করতে চান পারে নোট প্রশ্ন, যা তুলে ধরে কেন এই সমাধান কেন এর নিকৃষ্ট হয়।
দেবসোলার

2
আমি জানি আপনি প্রশ্ন জিজ্ঞাসা করেছেন, আপনি এই উত্তরটি লিখেছিলেন এবং আপনি খারাপ উত্তরটি গ্রহণ করেছেন। সে কারণেই আমি এটি সেভাবে বলেছি। গৃহীত উত্তরটি খারাপ হওয়ার কারণ হ'ল এটি রেফারেন্সের মাধ্যমে অ্যারে পাস করার চেষ্টা করছে, যা আপনাকে সত্যই এড়ানো উচিত। এছাড়াও, উদাহরণটি একক স্ট্রিংয়ে একাধিক যুক্তি ছড়িয়ে দেয়। আপনার যদি সত্যিই রেফারেন্সের মাধ্যমে অ্যারে পাস করার প্রয়োজন হয় তবে বাশ হ'ল এটিই ভুল ভাষা। এমনকি বাশ ৪.৩ এর নতুন নেমরেফ ভেরিয়েবলগুলি থাকা সত্ত্বেও আপনি নিরাপদে নামের সংঘর্ষ (বৃত্তাকার উল্লেখ) এড়াতে পারবেন না।
গিরিহা

4
ঠিক আছে, আপনি যদি প্রতিটি অ্যারের উপাদানের সংখ্যা অন্তর্ভুক্ত করেন তবে আপনি একাধিক অ্যারে পাস করতে পারেন। called_function "${#array[@]}" "${array[@]}" "${#array2[@]}" "${array2[@]}"ইত্যাদি ... এখনও কিছু স্পষ্ট বিধিনিষেধের সাথে, তবে ভাষাটি অন্যভাবে যেমন ভাষা ব্যবহার করতে ব্যবহৃত হয় তেমনভাবে ভাষাটিকে বাঁকানোর চেষ্টা করার চেয়ে ভাষাটি সমর্থন করে এমনভাবে সমস্যাটি সমাধান করা আরও ভাল।
গিরিহা

1
@ গিরিহা: ভাল, আমি অনুমান করি যে আমাদের একমত হতে হবে যে আমরা সম্মত নই, এবং আপনাকে আমাকে বিচারক হতে হবে যার উত্তরটি আমার প্রশ্নের উত্তরের জবাব দেয়। ব্যক্তিগতভাবে, আমি যেকোন উপায়ে রেফারেন্সের মাধ্যমে অ্যারে পাস করা পছন্দ করি (ভাষার কোনও বিষয় নয়, ডেটা অনুলিপি সংরক্ষণ করতে); আরও বেশি তাই যখন বিকল্পটি পিছনের দিকে বাঁকানো হয় এবং অতিরিক্ত প্যারামিটার হিসাবে অ্যারের আকারটি পাস করা হয় ...
দেবসোলার

38

কেন বার্টেলসন সমাধান সম্পর্কে মন্তব্য করা এবং জ্যান হেটিচের উত্তর:

কিভাবে এটা কাজ করে

takes_ary_as_arg descTable[@] optsTable[@]লাইন try_with_local_arys()ফাংশন পাঠায়:

  1. এটি আসলে ফাংশনে অ্যাক্সেসযোগ্য descTableএবং optsTableঅ্যারেগুলির একটি অনুলিপি তৈরি takes_ary_as_argকরে।
  2. takes_ary_as_arg()ফাংশন পায় descTable[@]এবং optsTable[@]স্ট্রিং, যে উপায় হিসেবে $1 == descTable[@]এবং $2 == optsTable[@]
  3. প্রারম্ভে takes_ary_as_arg()ফাংশন এটি ব্যবহার করে ${!parameter}বাক্য গঠন, যা বলা হয় পরোক্ষ রেফারেন্স বা কখনও কখনও ডবল রেফারেন্সড , এর অর্থ এই যে ব্যবহারের পরিবর্তে $1'র মান, আমরা মান ব্যবহার প্রসারিত মান$1 , যেমন:

    baba=booba
    variable=baba
    echo ${variable} # baba
    echo ${!variable} # booba

    অনুরূপ জন্য $2

  4. এটিকে যুক্ত argAry1=("${!1}")করে সরাসরি লেখার মতোই প্রসারিত argAry1একটি অ্যারে (বন্ধনীগুলি অনুসরণ করে =) হিসাবে তৈরি করে । সেখানে প্রয়োজন হয় না।descTable[@]argAry1=("${descTable[@]}")declare

বিশেষ দ্রষ্টব্য: উল্লেখ্য অ্যারের এই বন্ধনী ফর্ম ব্যবহার আরম্ভের মূল্য অনুযায়ী নতুন অ্যারে সূচনা হয় IFSবা অভ্যন্তরীণ ফিল্ড পৃথককারী যা ডিফল্টভাবে হয় ট্যাব , সম্পর্কে newline এবং স্থান[@]সেক্ষেত্রে , যেহেতু এটি স্বরলিপি ব্যবহার করেছে প্রতিটি উপাদানকে নিজেই দেখা যায় যেন তিনি উদ্ধৃত (বিপরীত [*])।

এটি দিয়ে আমার রিজার্ভেশন

ইন BASH, স্থানীয় পরিবর্তনশীল সুযোগ হ'ল বর্তমান ফাংশন এবং এটি থেকে আনা প্রতিটি শিশু ফাংশন, এটি এটি অনুবাদ করে যে takes_ary_as_arg()ফাংশনটি তাদের descTable[@]এবং optsTable[@]অ্যারেগুলিকে "দেখায়" , সুতরাং এটি কাজ করছে (উপরের ব্যাখ্যাটি দেখুন)।

সেক্ষেত্রে হ'ল, কেন সরাসরি সেই পরিবর্তনশীলগুলি নিজেরাই তাকান না? এটি ঠিক সেখানে লেখার মতো:

argAry1=("${descTable[@]}")

উপরের ব্যাখ্যাটি দেখুন, যা কেবল descTable[@]বর্তমান অনুসারে অ্যারের মানগুলি অনুলিপি করে IFS

সংক্ষেপে

যথারীতি এটি মান দিয়ে কিছুই পাস করছে না।

আমি উপরের ডেনিস উইলিয়ামসনের মন্তব্যেও জোর দিতে চাই: স্পার্স অ্যারে (সমস্ত কীগুলি সংজ্ঞায়িত করে অ্যারে - "গর্তগুলির মধ্যে") প্রত্যাশার মতো কাজ করবে না - আমরা কীগুলি আলগা করব এবং অ্যারে "ঘনীভূত" করব।

বলা হচ্ছে, আমি সাধারণীকরণের মান দেখতে পাচ্ছি, ফাংশনগুলি নামগুলি না জেনে অ্যারেগুলি (বা অনুলিপিগুলি) পেতে পারে:

  • ~ "অনুলিপিগুলির" জন্য: এই কৌশলটি যথেষ্ট ভাল, কেবল সচেতন হওয়া দরকার, সূচকগুলি (কীগুলি) চলে গেছে।
  • আসল অনুলিপিগুলির জন্য: আমরা কীগুলির জন্য একটি ইওল ব্যবহার করতে পারি, উদাহরণস্বরূপ:

    eval local keys=(\${!$1})

এবং তারপরে একটি অনুলিপি তৈরি করতে একটি লুপ ব্যবহার করুন। দ্রষ্টব্য: এখানে !এটি পূর্বের পরোক্ষ / ডাবল মূল্যায়ন ব্যবহৃত হয় না, বরং অ্যারের প্রসঙ্গে এটি অ্যারে সূচকগুলি (কীগুলি) প্রদান করে।

  • এবং, অবশ্যই, যদি আমরা পাস descTableএবং optsTableস্ট্রিংগুলি (ছাড়াই [@]) করি তবে আমরা অ্যারেটি নিজেই (রেফারেন্স অনুসারে) ব্যবহার করতে পারতাম eval। জেনেরিক ফাংশনের জন্য যা অ্যারে গ্রহণ করে।

2
কেন বার্টেলসন ব্যাখ্যার পিছনে প্রক্রিয়াটির ভাল ব্যাখ্যা। "এই কেস হওয়ার কারণে, কেন সরাসরি সেই ভেরিয়েবলগুলি তাদের নিজের দিকে নজর দেওয়া যায় না?", আমি উত্তর দেব: কেবল ফাংশনটির পুনরায় ব্যবহারের জন্য। ধরা যাক আমার সাথে একটি ফাংশন কল করা দরকার Array1, তারপরে Array2অ্যারের নামগুলি পাস করা সহজ হয়ে যায়।
জিফ্রিগন

দুর্দান্ত উত্তর, আমাদের এর মতো আরও ব্যাখ্যা দরকার!
ouডার্ড লোপেজ

22

এখানে মূল সমস্যাটি হ'ল ব্যাশ বিকাশকারী (গুলি) যে নকশাকৃত / প্রয়োগকারী অ্যারেগুলি সত্যিই পোচটিকে স্ক্রু করেছিল। তারা সিদ্ধান্ত নিয়েছে যে ${array}এটির জন্য খুব ছোট হাত ছিল ${array[0]}, যা একটি খারাপ ভুল ছিল। বিশেষত যখন আপনি বিবেচনা করেন যে ${array[0]}এর কোনও অর্থ নেই এবং অ্যারের প্রকারটি সাহসী হলে খালি স্ট্রিংয়ের মূল্যায়ন করে।

একটি অ্যারে array=(value1 ... valueN)নির্ধারণ করা এমন ফর্মটি গ্রহণ করে যেখানে মানটির বাক্য গঠন থাকে [subscript]=string, যার ফলে অ্যারেতে একটি নির্দিষ্ট সূচকে সরাসরি একটি মান নির্ধারিত হয়। এটি এটিকে তাই করে তোলে যাতে দুটি ধরণের অ্যারে থাকতে পারে, সংখ্যাগতভাবে সূচকযুক্ত এবং হ্যাশ সূচকযুক্ত (বাশ পার্লেন্সে এসোসিয়েটিভ অ্যারে নামে পরিচিত)। এটি এটিকেও তৈরি করে যাতে আপনি স্পারস সংখ্যাসূচকভাবে সূচিযুক্ত অ্যারে তৈরি করতে পারেন। বন্ধ করে ছেড়ে যাওয়া [subscript]=অংশ, একটি সংখ্যাসূচকভাবে সূচীবদ্ধ অ্যারে সংক্ষিপ্ত হাত 0 পূরণবাচক সূচক দিয়ে শুরু এবং নিয়োগ বিবৃতিতে প্রতিটি নতুন মান বৃদ্ধিশীল।

সুতরাং, পুরো অ্যারে, সূচী এবং সমস্তকে ${array}মূল্যায়ন করা উচিত । এটি অ্যাসাইনমেন্ট স্টেটমেন্টের বিপরীতে মূল্যায়ন করা উচিত। যে কোনও তৃতীয় বর্ষের সিএস মেজরের এটি জানা উচিত। সেক্ষেত্রে এই কোডটি ঠিক তেমন কাজ করবে যেমনটি আপনি এটি আশা করতে পারেন:

declare -A foo bar
foo=${bar}

তারপরে, ফাংশনগুলিকে মান দিয়ে অ্যারে পাস করা এবং একটি অ্যারে অন্যকে নির্ধারণ করা শেল সিনট্যাক্সের বাকী নির্দেশ হিসাবে কাজ করবে। তবে তারা এই সঠিকভাবে না করায়, অ্যাসাইনমেন্ট অপারেটর =অ্যারেগুলির জন্য কাজ করে না, এবং অ্যারেগুলি বিন্যাসের দ্বারা বা সাব-শেলগুলি বা আউটপুটটিতে সাধারণ ( echo ${array}) দ্বারা সমস্ত কিছু চিবানোর কোড ছাড়াই পাস করা যায় না।

সুতরাং, যদি এটি সঠিকভাবে করা হয়ে থাকে তবে নিম্নলিখিত উদাহরণটি দেখায় যে ব্যাশে অ্যারেগুলির কার্যকারিতা কীভাবে আরও ভাল হতে পারে:

simple=(first=one second=2 third=3)
echo ${simple}

ফলাফল আউটপুট হতে হবে:

(first=one second=2 third=3)

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

declare -A foo
read foo <file

হায় আফসোস, আমাদেরকে অন্যথায় চূড়ান্তভাবে বাশ বিকাশকারী দল হতাশ করেছে।

যেমন একটি ফাংশনে অ্যারে পাস করার জন্য সত্যিই কেবল একটি বিকল্প রয়েছে এবং তা হল নামফের বৈশিষ্ট্যটি ব্যবহার করা:

function funky() {
    local -n ARR

    ARR=$1
    echo "indexes: ${!ARR[@]}"
    echo "values: ${ARR[@]}"
}

declare -A HASH

HASH=([foo]=bar [zoom]=fast)
funky HASH # notice that I'm just passing the word 'HASH' to the function

নিম্নলিখিত ফলাফলের ফলাফল হবে:

indexes: foo zoom
values: bar fast

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

funky "${!array[*]}" "${array[*]}"

এবং তারপরে অ্যারেটিকে পুনরায় সাজানোর জন্য ফাংশনের অভ্যন্তরে একটি গোছা কোড লিখে writing


1
ব্যবহারের সমাধান local -nগৃহীত উত্তরের চেয়ে আরও ভাল এবং আধুনিক। এই দ্রবণটি যে কোনও ধরণের পরিবর্তনের জন্যও কাজ করবে। এই উত্তরের তালিকাভুক্ত উদাহরণটি ছোট করা যেতে পারে local -n ARR=${1}। তবে / এর -nবিকল্প কেবল বাশ সংস্করণে 4.3 এবং তত উপরে উপলব্ধ। localdeclare
রিচার্ডজিমসকিন্স

এটা সুন্দর! ছোট গোচা: আপনি যদি নিজের ফাংশনের স্থানীয় আর্গুমেন্ট (যেমন funky ARR) এর সাথে একই নামের সাথে একটি ভেরিয়েবল পাস করেন তবে শেলটি সতর্কতা দেবে circular name reference, কারণ মূলত ফাংশনটি চেষ্টা করার চেষ্টা করবে local -n ARR=ARR। এই বিষয় সম্পর্কে ভাল আলোচনা
জিন পাভলভস্কি

5

দেবসোলারের উত্তরের একটি পয়েন্ট রয়েছে যা আমি বুঝতে পারি না (সম্ভবত এটি করার একটি নির্দিষ্ট কারণ আছে তবে আমি তার একটিও ভাবতে পারি না): তিনি অবস্থানগত পরামিতি উপাদান থেকে উপাদানটিকে পুনরাবৃত্তির মাধ্যমে অ্যারে সেট করে।

একটি সহজ উত্সাহ হতে হবে

called_function()
{
  ...
  # do everything like shown by DevSolar
  ...

  # now get a copy of the positional parameters
  local_array=("$@")
  ...
}

1
এটি না করার জন্য আমার কারণ হ'ল আমি কয়েক দিন আগে পর্যন্ত বাশ অ্যারেগুলিতে মোটেই খেলিনি। পূর্বে আমি পার্ল পরিবর্তন করে যদি এটি জটিল হয়ে যায়, এমন একটি বিকল্প আমার বর্তমান কাজে নেই at ইঙ্গিতটির জন্য ধন্যবাদ!
দেবসোলার


3

প্যারামিটার হিসাবে কয়েকটি অ্যারে পাস করার একটি সহজ উপায় হ'ল অক্ষর দ্বারা পৃথক স্ট্রিং ব্যবহার করা। আপনি আপনার স্ক্রিপ্টটিকে এভাবে কল করতে পারেন:

./myScript.sh "value1;value2;value3" "somethingElse" "value4;value5" "anotherOne"

তারপরে, আপনি এটি আপনার কোডে এটি বের করতে পারেন:

myArray=$1
IFS=';' read -a myArray <<< "$myArray"

myOtherArray=$3
IFS=';' read -a myOtherArray <<< "$myOtherArray"

এইভাবে, আপনি প্যারামিটার হিসাবে বাস্তবে একাধিক অ্যারে পাস করতে পারেন এবং এটি শেষ পরামিতি হতে হবে না।


1

এই এক এমনকি স্পেস সঙ্গে কাজ করে:

format="\t%2s - %s\n"

function doAction
{
  local_array=("$@")
  for (( i = 0 ; i < ${#local_array[@]} ; i++ ))
    do
      printf "${format}" $i "${local_array[$i]}"
  done
  echo -n "Choose: "
  option=""
  read -n1 option
  echo ${local_array[option]}
  return
}

#the call:
doAction "${tools[@]}"

2
আমি ভাবছি এখানে কী আছে। এটি কেবল সাধারণ যুক্তি পাস হচ্ছে। "$ @" সিনট্যাক্সটি স্পেসে কাজ করার জন্য তৈরি করা হয়েছে: "$ @" "$ 1" "$ 2" এর সমতুল্য ...
আন্দ্রেস স্পিন্ডার

আমি কি কোনও ফাংশনে 2 টি অ্যারে পাস করতে পারি?
পাইেন্টেজি

1

কয়েকটি কৌশল দ্বারা আপনি অ্যারে সহ নামকরণের প্যারামিটারগুলি কার্যক্রমে যেতে পারেন।

আমি যে পদ্ধতিটি বিকাশ করেছি তা আপনাকে এরকম কোনও ফাংশনে পাস করা প্যারামিটারগুলি অ্যাক্সেস করার অনুমতি দেয়:

testPassingParams() {

    @var hello
    l=4 @array anArrayWithFourElements
    l=2 @array anotherArrayWithTwo
    @var anotherSingle
    @reference table   # references only work in bash >=4.3
    @params anArrayOfVariedSize

    test "$hello" = "$1" && echo correct
    #
    test "${anArrayWithFourElements[0]}" = "$2" && echo correct
    test "${anArrayWithFourElements[1]}" = "$3" && echo correct
    test "${anArrayWithFourElements[2]}" = "$4" && echo correct
    # etc...
    #
    test "${anotherArrayWithTwo[0]}" = "$6" && echo correct
    test "${anotherArrayWithTwo[1]}" = "$7" && echo correct
    #
    test "$anotherSingle" = "$8" && echo correct
    #
    test "${table[test]}" = "works"
    table[inside]="adding a new value"
    #
    # I'm using * just in this example:
    test "${anArrayOfVariedSize[*]}" = "${*:10}" && echo correct
}

fourElements=( a1 a2 "a3 with spaces" a4 )
twoElements=( b1 b2 )
declare -A assocArray
assocArray[test]="works"

testPassingParams "first" "${fourElements[@]}" "${twoElements[@]}" "single with spaces" assocArray "and more... " "even more..."

test "${assocArray[inside]}" = "adding a new value"

অন্য কথায়, কেবলমাত্র আপনি নিজের প্যারামিটারগুলিকে তাদের নামে কল করতে পারবেন না (যা আরও বেশি পাঠযোগ্য কোর তৈরি করে) আপনি আসলে অ্যারেগুলি পাস করতে পারেন (এবং ভেরিয়েবলের উল্লেখ - এই বৈশিষ্ট্যটি যদিও কেবল বাশ ৪.৩ এ কাজ করে)! এছাড়াও, ম্যাপযুক্ত ভেরিয়েবলগুলি সমস্ত স্থানীয় স্কোপে যেমন ঠিক $ 1 (এবং অন্যান্য)।

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

Function.AssignParamLocally() {
    local commandWithArgs=( $1 )
    local command="${commandWithArgs[0]}"

    shift

    if [[ "$command" == "trap" || "$command" == "l="* || "$command" == "_type="* ]]
    then
        paramNo+=-1
        return 0
    fi

    if [[ "$command" != "local" ]]
    then
        assignNormalCodeStarted=true
    fi

    local varDeclaration="${commandWithArgs[1]}"
    if [[ $varDeclaration == '-n' ]]
    then
        varDeclaration="${commandWithArgs[2]}"
    fi
    local varName="${varDeclaration%%=*}"

    # var value is only important if making an object later on from it
    local varValue="${varDeclaration#*=}"

    if [[ ! -z $assignVarType ]]
    then
        local previousParamNo=$(expr $paramNo - 1)

        if [[ "$assignVarType" == "array" ]]
        then
            # passing array:
            execute="$assignVarName=( \"\${@:$previousParamNo:$assignArrLength}\" )"
            eval "$execute"
            paramNo+=$(expr $assignArrLength - 1)

            unset assignArrLength
        elif [[ "$assignVarType" == "params" ]]
        then
            execute="$assignVarName=( \"\${@:$previousParamNo}\" )"
            eval "$execute"
        elif [[ "$assignVarType" == "reference" ]]
        then
            execute="$assignVarName=\"\$$previousParamNo\""
            eval "$execute"
        elif [[ ! -z "${!previousParamNo}" ]]
        then
            execute="$assignVarName=\"\$$previousParamNo\""
            eval "$execute"
        fi
    fi

    assignVarType="$__capture_type"
    assignVarName="$varName"
    assignArrLength="$__capture_arrLength"
}

Function.CaptureParams() {
    __capture_type="$_type"
    __capture_arrLength="$l"
}

alias @trapAssign='Function.CaptureParams; trap "declare -i \"paramNo+=1\"; Function.AssignParamLocally \"\$BASH_COMMAND\" \"\$@\"; [[ \$assignNormalCodeStarted = true ]] && trap - DEBUG && unset assignVarType && unset assignVarName && unset assignNormalCodeStarted && unset paramNo" DEBUG; '
alias @param='@trapAssign local'
alias @reference='_type=reference @trapAssign local -n'
alias @var='_type=var @param'
alias @params='_type=params @param'
alias @array='_type=array @param'

1

কেবল গৃহীত উত্তরের সাথে যুক্ত করার জন্য, যেমন আমি পেয়েছি যে অ্যারের সামগ্রীগুলি এমনভাবে তৈরি করা থাকলে এটি ভাল কাজ করে না:

RUN_COMMANDS=(
  "command1 param1... paramN"
  "command2 param1... paramN"
)

এই ক্ষেত্রে অ্যারের প্রতিটি সদস্য বিভক্ত হয়ে যায়, সুতরাং ফাংশনটি যে অ্যারে দেখায় তা সমান:

RUN_COMMANDS=(
    "command1"
    "param1"
     ...
    "command2"
    ...
)

এই কেসটি কাজ করতে, আমি যেভাবে খুঁজে পেয়েছি তা হল ভেরিয়েবলের নামটি ফাংশনে প্রেরণ করা, তারপরে eval ব্যবহার করুন:

function () {
    eval 'COMMANDS=( "${'"$1"'[@]}" )'
    for COMMAND in "${COMMANDS[@]}"; do
        echo $COMMAND
    done
}

function RUN_COMMANDS

শুধু আমার 2 ©


1

এটি যতটা কুৎসিত, এখানে এমন একটি কাজ রয়েছে যা আপনি পরিষ্কারভাবে অ্যারে পাস না করে ততক্ষণ কাজ করে তবে একটি অ্যারের সাথে সম্পর্কিত একটি পরিবর্তনশীল:

function passarray()
{
    eval array_internally=("$(echo '${'$1'[@]}')")
    # access array now via array_internally
    echo "${array_internally[@]}"
    #...
}

array=(0 1 2 3 4 5)
passarray array # echo's (0 1 2 3 4 5) as expected

আমি নিশ্চিত কেউ ধারণাটির একটি পরিষ্কার বাস্তবায়ন নিয়ে আসতে পারে, তবে আমি এটি অ্যারে পাস "{array[@]"}করার পরে অভ্যন্তরীণভাবে ব্যবহার করে অ্যাক্সেস করার চেয়ে ভাল সমাধান হিসাবে এটি পেয়েছি array_inside=("$@")। অন্যান্য অবস্থানগত / getoptsপরামিতি থাকলে এটি জটিল হয় । এই ক্ষেত্রে, আমাকে প্রথমে নির্ধারণ করতে হবে এবং তারপরে shiftঅ্যারে উপাদানগুলির অপসারণের কিছু সংমিশ্রণ ব্যবহার করে অ্যারের সাথে সম্পর্কিত নয় এমন পরামিতিগুলি সরিয়ে ফেলতে হয়েছিল ।

একটি পিউরিস্ট দৃষ্টিভঙ্গি সম্ভবত এই পদ্ধতির ভাষাকে লঙ্ঘন হিসাবে দেখেছে, তবে বাস্তবিকভাবে বলতে গেলে এই পদ্ধতির ফলে আমার অনেক দুঃখ বাঁচিয়েছে। সম্পর্কিত বিষয়ে, আমি ফাংশনে যে evalপ্যারামিটারটি target_varnameদিয়েছি তার অনুসারে একটি ভেরিয়েবলের অভ্যন্তরীণভাবে নির্মিত অ্যারে নির্ধারণ করতে ব্যবহার করি:

eval $target_varname=$"(${array_inside[@]})"

আশা করি এটি কাউকে সাহায্য করবে।


0

প্রয়োজনীয়তা : একটি অ্যারেতে একটি স্ট্রিং সন্ধান করার জন্য ফাংশন।
এটি দেবসোলারের সমাধানটির একটি সামান্য সরলকরণ যাতে এটি অনুলিপি না করে পাস হওয়া যুক্তিগুলি ব্যবহার করে।

myarray=('foobar' 'foxbat')

function isInArray() {
  local item=$1
  shift
  for one in $@; do
    if [ $one = $item ]; then
      return 0   # found
    fi
  done
  return 1       # not found
}

var='foobar'
if isInArray $var ${myarray[@]}; then
  echo "$var found in array"
else
  echo "$var not found in array"
fi 

0

আমার সংক্ষিপ্ত উত্তরটি হ'ল:

function display_two_array {
    local arr1=$1
    local arr2=$2
    for i in $arr1
    do
       "arrary1: $i"
    done
    
    for i in $arr2
    do
       "arrary2: $i"
    done
}

test_array=(1 2 3 4 5)
test_array2=(7 8 9 10 11)

display_two_array "${test_array[*]}" "${test_array2[*]}"
এটি লক্ষ করা উচিত যে ${test_array[*]}এবং ${test_array2[*]}"" এর চারপাশে থাকা উচিত, অন্যথায় আপনি ব্যর্থ হবেন।


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