ফাংশন আর্গুমেন্ট হিসাবে একটি অ্যারে কিভাবে পাস করবেন?


57

আর্গুমেন্ট হিসাবে একটি অ্যারে পাস করার জন্য কিছুক্ষণ সংগ্রাম করা কিন্তু এটি কোনওভাবেই কাজ করছে না। আমি নীচের মত চেষ্টা করেছি:

#! /bin/bash

function copyFiles{
   arr="$1"
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one" "two" "three")

copyFiles $array

ব্যাখ্যা সহ একটি উত্তর সুন্দর হবে।

সম্পাদনা: মূলত, আমি শেষ পর্যন্ত অন্য স্ক্রিপ্ট ফাইল থেকে ফাংশনটি কল করব। Plz সম্ভব হলে বাধাগুলি ব্যাখ্যা করুন explain

উত্তর:


84
  • কোনও সূচি ছাড়াই একটি অ্যারের প্রসারিত করা কেবল প্রথম উপাদানটি দেয়, ব্যবহার করে

    copyFiles "${array[@]}"

    পরিবর্তে

    copyFiles $array
  • শি-ব্যাং ব্যবহার করুন

    #!/bin/bash
  • সঠিক ফাংশন সিনট্যাক্স ব্যবহার করুন

    বৈধ রূপগুলি হয়

    function copyFiles {…}
    function copyFiles(){…}
    function copyFiles() {…}

    পরিবর্তে

    function copyFiles{…}
  • অ্যারে প্যারামিটারটি পেতে ডান সিনট্যাক্সটি ব্যবহার করুন

    arr=("$@")

    পরিবর্তে

    arr="$1"

অতএব

#!/bin/bash
function copyFiles() {
   arr=("$@")
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one" "two" "three")

copyFiles "${array[@]}"

আউটপুট হল (আমার স্ক্রিপ্টটির নাম আছে foo)

$ ./foo   
one
two
three

ধন্যবাদ, তবে ফাংশন কপি ফাইলগুলি নয় F…} একটি সঠিক বাক্য গঠন? যদিও আমি একটি নতুন বিআই আমি সিনট্যাক্স দিয়ে সফলভাবে কিছু প্রোগ্রাম চালাচ্ছি।
আহসানুল হক

বৈধ রূপগুলি হয় copyFiles {…}এবং copyFiles(){…}এবং copyFiles() {…}তবে তা নয় copyFiles{…}। ভেরিয়েন্টে স্পেসটি নোট করুন()
AB

19

আপনি যদি এক বা একাধিক আর্গুমেন্ট এবং একটি অ্যারে পাস করতে চান তবে আমি @AB এর স্ক্রিপ্টে এই পরিবর্তনটি প্রস্তাব করছি অ্যারেটি সর্বশেষ যুক্তি
হওয়া উচিত এবং কেবল একটি অ্যারে পাস করা যেতে পারে

#!/bin/bash
function copyFiles() {
   local msg="$1"   # Save first argument in a variable
   shift            # Shift all arguments to the left (original $1 gets lost)
   local arr=("$@") # Rebuild the array with rest of arguments
   for i in "${arr[@]}";
      do
          echo "$msg $i"
      done
}

array=("one" "two" "three")

copyFiles "Copying" "${array[@]}"

আউটপুট:

$ ./foo   
Copying one
Copying two
Copying three

2
অ্যারে সম্পর্কে শিখতে +1 শেষে থাকা দরকার এবং কেবল একটিই প্রেরণ করা উচিত
ডেভিড 'দ্য টাল আদা'

1
shiftব্যবহারের জন্য ধন্যবাদ ।
ইটাচি

কখনও কখনও শিফটের যুক্তি ব্যবহার করাও দরকারী, সুতরাং অ্যারের আগে যদি আপনার 6 টি যুক্তি থাকে তবে আপনি ব্যবহার করতে পারেন shift 6
স্পিনআপ

আপনি "বাকী যুক্তি" কে রূপান্তর করুন arr। মাঝখানে অ্যারে প্যারামিটার রাখা কি সম্ভব? এমনকি বেশ কয়েকটি অ্যারে পরামিতি? function copyAndMove() { msg1=$1 ; arr1=...?... ; msg2=? ; arr2=...?... ; msg3=? ; ... }। আমি পাইথন এটা সংজ্ঞায়িত হবে: def copyAndMove(msg1="foo", cpFiles=[], msg2="bar", mvFiles=[], msg3="baz"): ...। কিছু মনে করবেন না, আমি দেখেছি stackoverflow.com/a/4017175/472245
towi

18

আপনি রেফারেন্স হিসাবে অ্যারে পাসও করতে পারেন। অর্থাৎ,

#!/bin/bash

function copyFiles {
   local -n arr=$1

   for i in "${arr[@]}"
   do
      echo "$i"
   done
}

array=("one" "two" "three")

copyFiles array

তবে মনে রাখবেন যে অ্যারেতে যে কোনও পরিবর্তন হয়েছে তা অ্যারেতে করা হবে।


1
যদিও, আমি যা চাই তা ঠিক তা নয়, তবে এটি কীভাবে বাশে রেফারেন্সের মাধ্যমে কাজ করে তা জেনে ভাল লাগল। +1 :)
আহসানুল হক

3
ব্যাশ 4.3+ প্রয়োজন
dtmland

8

সমস্যা আছে কয়েক। এখানে কার্যকারী ফর্মটি রয়েছে:

#!/bin/bash
function copyFiles {
   arr=( "$@" )
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one" "two" "three")
copyFiles "${array[@]}"
  • ফাংশন ঘোষণা এবং এর মধ্যে কমপক্ষে একটি স্থান থাকা দরকার {

  • আপনি ব্যবহার করতে পারবেন না $array, যেমন arrayএকটি অ্যারে যেমন চলক নয়। আপনি যদি অ্যারে ব্যবহারের সমস্ত মান পেতে চান"${array[@]}"

  • আপনার প্রধান ফাংশন ঘোষণায় আপনার প্রয়োজন arr="$@"যেমন "${array[@]}"স্থানগুলি দ্বারা পৃথক সূচকযুক্ত মানগুলিতে প্রসারিত হবে, আপনি যদি ব্যবহার করেন তবে আপনি $1কেবল প্রথম মান পাবেন get সমস্ত মান ব্যবহার করতে arr="$arr[@]}"


আপনার প্রয়োজনarr=("$@")
এবি

পার্থক্যটি দেখতে, breakনীচে একটি যুক্ত করুন echo "$i"। আপনার সংস্করণে আপনি এখনও সমস্ত উপাদান দেখতে পাবেন। তবে এটি তিনটি লাইন হওয়া উচিত।
এবি

@ হেইমাইল: ছোট টাইপো - দ্বিতীয় বুলেটের অ্যারেটি missing হারিয়ে গেছে ... "$ {অ্যারে [@]}" ...
সিবিহে

3

এখানে কিছুটা বড় উদাহরণ অনুসরণ করা হয়। ব্যাখ্যা জন্য, কোড মন্তব্য দেখুন।

#!/bin/bash -u
# ==============================================================================
# Description
# -----------
# Show the content of an array by displaying each element separated by a
# vertical bar (|).
#
# Arg Description
# --- -----------
# 1   The array
# ==============================================================================
show_array()
{
    declare -a arr=("${@}")
    declare -i len=${#arr[@]}
    # Show passed array
    for ((n = 0; n < len; n++))
    do
        echo -en "|${arr[$n]}"
    done
    echo "|"
}

# ==============================================================================
# Description
# -----------
# This function takes two arrays as arguments together with their sizes and a
# name of an array which should be created and returned from this function.
#
# Arg Description
# --- -----------
# 1   Length of first array
# 2   First array
# 3   Length of second array
# 4   Second array
# 5   Name of returned array
# ==============================================================================
array_demo()
{
    declare -a argv=("${@}")                           # All arguments in one big array
    declare -i len_1=${argv[0]}                        # Length of first array passad
    declare -a arr_1=("${argv[@]:1:$len_1}")           # First array
    declare -i len_2=${argv[(len_1 + 1)]}              # Length of second array passad
    declare -a arr_2=("${argv[@]:(len_1 + 2):$len_2}") # Second array
    declare -i totlen=${#argv[@]}                      # Length of argv array (len_1+len_2+2)
    declare __ret_array_name=${argv[(totlen - 1)]}     # Name of array to be returned

    # Show passed arrays
    echo -en "Array 1: "; show_array "${arr_1[@]}"
    echo -en "Array 2: "; show_array "${arr_2[@]}"

    # Create array to be returned with given name (by concatenating passed arrays in opposite order)
    eval ${__ret_array_name}='("${arr_2[@]}" "${arr_1[@]}")'
}

########################
##### Demo program #####
########################
declare -a array_1=(Only 1 word @ the time)                                       # 6 elements
declare -a array_2=("Space separated words," sometimes using "string paretheses") # 4 elements
declare -a my_out # Will contain output from array_demo()

# A: Length of array_1
# B: First array, not necessary with string parentheses here
# C: Length of array_2
# D: Second array, necessary with string parentheses here
# E: Name of array that should be returned from function.
#          A              B             C              D               E
array_demo ${#array_1[@]} ${array_1[@]} ${#array_2[@]} "${array_2[@]}" my_out

# Show that array_demo really returned specified array in my_out:
echo -en "Returns: "; show_array "${my_out[@]}"

1

সর্বোত্তম উপায় হ'ল অবস্থান আর্গুমেন্ট হিসাবে পাস করা। আর কিছু না. আপনি স্ট্রিং হিসাবে পাস হতে পারে, কিন্তু এই উপায় কিছু ঝামেলা হতে পারে। উদাহরণ:

array=(one two three four five)

function show_passed_array(){
  echo $@
}

অথবা

function show_passed_array(){
  while $# -gt 0;do
    echo $1;shift
  done
}

    show_passed_array ${array[@]}

আউটপুট:

  one two three four five

আপনার অর্থ যদি অ্যারের মানটিতে স্থান চিহ্ন থাকে তবে আপনাকে ফাংশনটিতে সূচক দ্বারা মান অ্যাক্সেসের জন্য পাসের আগে উপাদানগুলির উদ্ধৃতি দিতে হবে $ 1 $ 2 $ 3 ... অবস্থানের পরামিতি। যেখানে সূচি 0 -> 1, 1 -> 2, ... অ্যাক্সেসের পুনরাবৃত্তি করতে সর্বদা $ 1 এবং শিফটের পরে ব্যবহার করা ভাল। অতিরিক্ত কিছু প্রয়োজন হয় না। আপনি এই জাতীয় কোনও অ্যারে ছাড়াই যুক্তিগুলি পাস করতে পারেন:

show_passed_array one two three four five

বাশ মিডিয়া স্বয়ংক্রিয়ভাবে পাস হওয়া আর্গুমেন্টগুলি থেকে একটি অ্যারে তৈরি করে যা সেগুলি ফাংশনে পাস করে এবং তারপরে আপনার অবস্থান আর্গুমেন্ট থাকে। তবুও আপনি যখন write {অ্যারে [2] write লিখেন তখন আপনি সত্যিকার অর্থে যুক্তিযুক্ত যুক্তিটি লিখুন এবং তিনটি চারটি ফাংশনে পৌঁছে দিন। সুতরাং সেই কলগুলি সমান।


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[@]})"

এটি কুৎসিত এবং অযৌক্তিক। যাদের নাম আপনি অ্যারের পাস করতে চান, করতে array_internally: এটা একজন ওরফে declare -n array_internally=$1। এবং এর বাকি অংশগুলি "জটিল হয়ে ওঠে" এবং "নির্ধারণ করুন এবং তারপরে অপসারণ করুন ..." আপনি কীভাবে অ্যারে পাস করবেন তা নির্বিশেষে প্রযোজ্য, সুতরাং এর বিন্দুটি আমি কী তা দেখতে পাচ্ছি না। এবং evalসম্ভাব্যভাবে বিশেষ অক্ষর সমন্বিত একটি অ্যারে তৈরি করা কেবল পরবর্তী তারিখে শোক হওয়ার জন্য অপেক্ষা করছে।
মারু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.