বাশ ফাংশনে প্যারামিটারগুলি পাস করা


980

আমি বাশ ফাংশনে কীভাবে পরামিতিগুলি পাস করতে পারি তা অনুসন্ধান করার চেষ্টা করছি, তবে যা আসে তা হ'ল কমান্ড লাইন থেকে পরামিতি কীভাবে পাস করতে হয়।

আমি আমার স্ক্রিপ্টের মধ্যে প্যারামিটারগুলি পাস করতে চাই। আমি চেষ্টা করেছিলাম:

myBackupFunction("..", "...", "xx")

function myBackupFunction($directory, $options, $rootPassword) {
     ...
}

কিন্তু সিনট্যাক্সটি সঠিক নয়, আমার ফাংশনে একটি প্যারামিটার কীভাবে পাস করবেন?


6
"... তবে যা আসে তা হ'ল কমান্ড লাইন থেকে প্যারামিটার কীভাবে পাস করতে হয়" - হ্যাঁ! এর কারণ বাশ স্ক্রিপ্টগুলি মূলত কমান্ড লাইনের ক্রম হয় - একটি বাশ স্ক্রিপ্টে কোনও ফাংশনটি অনুরোধ করে যেমন এটি কমান্ড লাইনের একটি কমান্ড! :-) আপনার কলটি আমার ব্যাকআপ ফাংশন হবে ".." "..." "xx"; কোন প্রথম বন্ধনী, কোন কমা নেই।
Wil

উত্তর:


1618

ফাংশন ঘোষণার দুটি সাধারণ উপায় রয়েছে ways আমি দ্বিতীয় পদ্ধতির পছন্দ।

function function_name {
   command...
} 

অথবা

function_name () {
   command...
} 

যুক্তি সহ একটি ফাংশন কল করতে:

function_name "$arg1" "$arg2"

ফাংশনটি তাদের অবস্থান অনুসারে পাস হওয়া যুক্তিগুলিকে বোঝায় (নাম নয়), যা $ 1, $ 2 এবং আরও অনেক কিছু। $ 0 হ'ল স্ক্রিপ্টের নাম।

উদাহরণ:

function_name () {
   echo "Parameter #1 is $1"
}

এছাড়াও, আপনার ফাংশনটি ঘোষণার পরে আপনাকে কল করতে হবে।

#!/usr/bin/env sh

foo 1  # this will fail because foo has not been declared yet.

foo() {
    echo "Parameter #1 is $1"
}

foo 2 # this will work.

আউটপুট:

./myScript.sh: line 2: foo: command not found
Parameter #1 is 2

রেফারেন্স: উন্নত ব্যাশ-স্ক্রিপ্টিং গাইড


4
আপনি স্থানগুলি ভুলে গেছেন, চেষ্টা করুন function name() {}। সম্ভবত 'এন্টার' দিয়ে আগে থাকতে হবে{}
lalo

21
ভাল উত্তর. আমার 2 সেন্ট: শেল নির্মান যে একটি ফাইল বসবাস যে sourced হয় (ডটেড) প্রয়োজন হলে, আমি ব্যবহার করতে পছন্দ functionশব্দ এবং() । আমার লক্ষ্য (কোনও ফাইলটিতে, কমান্ড লাইন নয়) স্বচ্ছতা বাড়াতে হয়, টাইপ করা অক্ষরের সংখ্যা হ্রাস না করা, যেমন function myBackupFunction() compound-statement,।
টেরি গার্ডনার

22
@ সিএমসিডিগ্রাগনকাই, functionকীওয়ার্ড সংস্করণটি একটি এক্সটেনশন; অন্য ফর্মটি সমস্ত পসিক্স-কমপ্লায়েন্ট শেলগুলিতে কাজ করে।
চার্লস ডাফি

8
@ টেরিগার্ডনার, বিবেচনা করুন যে আপনার স্বচ্ছতা বাড়াতে আপনার প্রচেষ্টা সামঞ্জস্যতা হ্রাস করছে।
চার্লস ডাফি

6
@ রনবার্ক, সম্ভবত - তবে আমরা কেবল স্বচ্ছতার বিষয়টি বিবেচনা করলেও, functionকীওয়ার্ডটির পুরানো ksh- পারিবারিক শেলগুলিতে গ্যারান্টি রয়েছে যা আধুনিক ব্যাশের সম্মান দেয় না (যেমন শাঁসগুলিতে, functionস্থানীয়ভাবে বাই-ডিফল্ট পরিবর্তনগুলি তৈরি করে; , এটা না). যেমন, এর ব্যবহারটি যে কেউ জানে তার পক্ষে স্পষ্টতা হ্রাস পায় এবং আশা করতে পারেন, ksh আচরণ। Wiki.bash-hackers.org/scriptting/obsolete
চার্লস ডাফি

68

উচ্চ স্তরের প্রোগ্রামিং ভাষার জ্ঞান (সি / সি ++ / জাভা / পিএইচপি / পাইথন / পার্ল ...) সাধারণ মানুষকে পরামর্শ দেবে যে বাশ ফাংশনগুলি অন্য ভাষাগুলির মতো কাজ করা উচিত। পরিবর্তে , বাশ ফাংশনগুলি শেল কমান্ডের মতো কাজ করে এবং শেল কমান্ডের (যেমন ls -l) বিকল্পটি যেমন পাস করতে পারে তেমনিভাবে তাদের কাছে আর্গুমেন্টগুলি পাস করার আশা করে । বাস্তবে, ব্যাশে ফাংশন আর্গুমেন্টগুলি অবস্থানগত পরামিতি ( $1, $2..$9, ${10}, ${11}এবং আরও কিছু) হিসাবে বিবেচনা করা হয়। এটি কীভাবে getoptsকাজ করে তা বিবেচনা করে অবাক হওয়ার কিছু নেই । ব্যাশে কোনও ফাংশন কল করতে বন্ধনী ব্যবহার করবেন না।


( দ্রষ্টব্য : আমি এই মুহুর্তে ওপেন সোলারিসে কাজ করে যাচ্ছি))

# bash style declaration for all you PHP/JavaScript junkies. :-)
# $1 is the directory to archive
# $2 is the name of the tar and zipped file when all is done.
function backupWebRoot ()
{
    tar -cvf - $1 | zip -n .jpg:.gif:.png $2 - 2>> $errorlog &&
        echo -e "\nTarball created!\n"
}


# sh style declaration for the purist in you. ;-)
# $1 is the directory to archive
# $2 is the name of the tar and zipped file when all is done.
backupWebRoot ()
{
    tar -cvf - $1 | zip -n .jpg:.gif:.png $2 - 2>> $errorlog &&
        echo -e "\nTarball created!\n"
}


# In the actual shell script
# $0               $1            $2

backupWebRoot ~/public/www/ webSite.tar.zip

ভেরিয়েবলের জন্য নাম ব্যবহার করতে চান। শুধু এই কাজ।

declare filename=$1 # declare gives you more options and limits variable scope

একটি ফাংশনে একটি অ্যারে পাস করতে চান?

callingSomeFunction "${someArray[@]}" # Expands to all array elements.

ফাংশনের অভ্যন্তরে, এই জাতীয় যুক্তিগুলি হ্যান্ডেল করুন।

function callingSomeFunction ()
{
    for value in "$@" # You want to use "$@" here, not "$*" !!!!!
    do
        :
    done
}

একটি মান এবং একটি অ্যারে পাস করার প্রয়োজন, তবে এখনও ফাংশনের ভিতরে "$ @" ব্যবহার করবেন?

function linearSearch ()
{
    declare myVar="$1"

    shift 1 # removes $1 from the parameter list

    for value in "$@" # Represents the remaining parameters.
    do
        if [[ $value == $myVar ]]
        then
            echo -e "Found it!\t... after a while."
            return 0
        fi
    done

    return 1
}

linearSearch $someStringValue "${someArray[@]}"

64

আপনি যদি নামকরণের প্যারামিটারগুলি পছন্দ করেন তবে নামকরণের প্যারামিটারগুলি কার্যক্রমে পাস করা (কয়েকটি কৌশল সহ) সম্ভব (এটি অ্যারে এবং রেফারেন্সও পাস করা সম্ভব করে)।

আমি যে পদ্ধতিটি বিকাশ করেছি তা আপনাকে এই জাতীয় ফাংশনে পাস করা নামকরণের পরামিতিগুলি সংজ্ঞায়িত করতে দেয়:

function example { args : string firstName , string lastName , integer age } {
  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}

আপনি @ প্রয়োজনীয় বা @ রিডোনলি হিসাবে আর্গুমেন্টগুলি টিকিয়ে রাখতে পারেন, তৈরি করতে পারেন ... আর্গুমেন্ট তৈরি করুন, অনুক্রমিক যুক্তিগুলি থেকে অ্যারে তৈরি করুন (যেমন ব্যবহার করে string[4]) এবং একাধিক লাইনে যুক্তিগুলি তালিকাভুক্ত করুন:

function example {
  args
    : @required string firstName
    : string lastName
    : integer age
    : string[] ...favoriteHobbies

  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
  echo "My favorite hobbies include: ${favoriteHobbies[*]}"
}

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

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

shopt -s expand_aliases

function assignTrap {
  local evalString
  local -i paramIndex=${__paramIndex-0}
  local initialCommand="${1-}"

  if [[ "$initialCommand" != ":" ]]
  then
    echo "trap - DEBUG; eval \"${__previousTrap}\"; unset __previousTrap; unset __paramIndex;"
    return
  fi

  while [[ "${1-}" == "," || "${1-}" == "${initialCommand}" ]] || [[ "${#@}" -gt 0 && "$paramIndex" -eq 0 ]]
  do
    shift # first colon ":" or next parameter's comma ","
    paramIndex+=1
    local -a decorators=()
    while [[ "${1-}" == "@"* ]]
    do
      decorators+=( "$1" )
      shift
    done

    local declaration=
    local wrapLeft='"'
    local wrapRight='"'
    local nextType="$1"
    local length=1

    case ${nextType} in
      string | boolean) declaration="local " ;;
      integer) declaration="local -i" ;;
      reference) declaration="local -n" ;;
      arrayDeclaration) declaration="local -a"; wrapLeft= ; wrapRight= ;;
      assocDeclaration) declaration="local -A"; wrapLeft= ; wrapRight= ;;
      "string["*"]") declaration="local -a"; length="${nextType//[a-z\[\]]}" ;;
      "integer["*"]") declaration="local -ai"; length="${nextType//[a-z\[\]]}" ;;
    esac

    if [[ "${declaration}" != "" ]]
    then
      shift
      local nextName="$1"

      for decorator in "${decorators[@]}"
      do
        case ${decorator} in
          @readonly) declaration+="r" ;;
          @required) evalString+="[[ ! -z \$${paramIndex} ]] || echo \"Parameter '$nextName' ($nextType) is marked as required by '${FUNCNAME[1]}' function.\"; " >&2 ;;
          @global) declaration+="g" ;;
        esac
      done

      local paramRange="$paramIndex"

      if [[ -z "$length" ]]
      then
        # ...rest
        paramRange="{@:$paramIndex}"
        # trim leading ...
        nextName="${nextName//\./}"
        if [[ "${#@}" -gt 1 ]]
        then
          echo "Unexpected arguments after a rest array ($nextName) in '${FUNCNAME[1]}' function." >&2
        fi
      elif [[ "$length" -gt 1 ]]
      then
        paramRange="{@:$paramIndex:$length}"
        paramIndex+=$((length - 1))
      fi

      evalString+="${declaration} ${nextName}=${wrapLeft}\$${paramRange}${wrapRight}; "

      # continue to the next param:
      shift
    fi
  done
  echo "${evalString} local -i __paramIndex=${paramIndex};"
}

alias args='local __previousTrap=$(trap -p DEBUG); trap "eval \"\$(assignTrap \$BASH_COMMAND)\";" DEBUG;'

কি কি @var, @reference, @paramsভেরিয়েবল? এই সম্পর্কে আরও জানতে আমি কীভাবে ইন্টারনেটে সন্ধান করব?
জিপসিকোসমোনট

3
দুর্দান্ত উত্তর! আমি সবেমাত্র ব্যাশ ইনফিনিটি গবেষণা করেছি এবং দেখে মনে হচ্ছে এটি সত্যিই সহায়ক হবে। ধন্যবাদ!
জোনাথন হাল্ট

ধন্যবাদ @ জনাথনহুল্ট! আমি সম্প্রতি আমার উপরের উত্তরটি সম্প্রতি আপডেট করেছি এবং এটি এখন একটি নতুন, বাশ ইনফিনিটি ২.০-তে থাকা কোডটিতে আবার লিখেছেন। আমি এটি পুনরায় লেখার কারণটি পুরানো বাস্তবায়নের বাগ (এটি গিটহাবের বিষয়গুলির মধ্যে রয়েছে) of নতুন সংস্করণটিকে আবার বাশ ইনফিনিটিতে একীভূত করার সময় হয়নি। শুনে সাহায্য পেয়ে খুশী হলাম।
নিনিয়ানি

হাই @niieani আমি যখন আপনি নিজের উত্তরে যে ফর্মটি ব্যবহার করেন তাতে বাশ ফাংশন তৈরি করার চেষ্টা করার সময় এটি আমাকে বলবে যে অ্যাপ থেকে ইউকমন উপকরণ ইনস্টল করা দরকার। আপনার বাশ স্ক্রিপ্টটি কী এভাবে কাজ করে? আমি কি এটি সঠিকভাবে করছি? যদি আমি বুঝতে পারি যে আপনি বা অন্য কেউ মূলত ব্যাশের একটি এক্সটেনশনের অনুমতি দেওয়ার জন্য ইউকমন ব্যবহারের প্রোগ্রামটি তৈরি করেছেন, তাই না?
ডেভিড এ ফ্রেঞ্চ

@ ডেভিডএ.ফ্রিঞ্চ নং, এটি হওয়া উচিত নয়। ucommonআমার কোডের সাথে কোনও সম্পর্ক নেই । এটি আপনার কাছে এমন কোনও সরঞ্জাম ইনস্টল থাকা সম্ভব হয়েছে যা আপনার উল্লিখিত সমস্যাটির কারণ হয়ে দাঁড়ায়, এটি কী হতে পারে তা ধারণা নেই।
নিইনি

27

পেরেনস এবং কমাগুলি মিস করুন:

 myBackupFunction ".." "..." "xx"

এবং ফাংশনটি দেখতে এইরকম হওয়া উচিত:

function myBackupFunction() {
   # here $1 is the first parameter, $2 the second etc.
}

8

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

#!/bin/bash

read -p "Enter the first  value: " x
read -p "Enter the second value: " y

add(){
    arg1=$1 #arg1 gets to be the first  assigned argument (note there are no spaces)
    arg2=$2 #arg2 gets to be the second assigned argument (note there are no spaces)

    echo $(($arg1 + $arg2))
}

add x y #feeding the arguments

6
নামটি দিয়ে সেই পদ্ধতিতে প্রবেশ করা কেবল সংখ্যক অপারেটর (()) এর মধ্যে পূর্ণ সংখ্যার জন্য কাজ করে এবং এটি কেবলমাত্র কাজ করে কারণ সংখ্যক অপারেটরটি পুনরাবৃত্তভাবে মানগুলির সাথে স্ট্রিংগুলি সমাধান করে। আপনি যদি আমার অর্থটি পরীক্ষা করতে চান তবে x এর জন্য '5' এবং তারপরে 'x' লিখুন এবং আপনি দেখতে পাবেন যে এটি যুক্ত হয় (x + y) = (5 + x) = (5 + 5) = 10. অন্যান্য সমস্ত ব্যবহারের ক্ষেত্রে আপনার উদাহরণ ব্যর্থ হবে। পরিবর্তে আপনার জেনেরিক কোডের জন্য '$ x "" $ y "' ব্যবহার করা উচিত।
Wil

6

একটি সাধারণ উদাহরণ যা কোনও ফাংশন কল করার সময় স্ক্রিপ্ট সম্পাদন করার সময় বা স্ক্রিপ্টের অভ্যন্তরে উভয়ই সাফ করে দেবে।

#!/bin/bash
echo "parameterized function example"
function print_param_value(){
    value1="${1}" # $1 represent first argument
    value2="${2}" # $2 represent second argument
    echo "param 1 is  ${value1}" #as string
    echo "param 2 is ${value2}"
    sum=$(($value1+$value2)) #process them as number
    echo "The sum of two value is ${sum}"
}
print_param_value "6" "4" #space sparted value
#you can also pass paramter durign executing script
print_param_value "$1" "$2" #parameter $1 and $2 during executing

#suppose our script name is param_example
# call like this 
# ./param_example 5 5
# now the param will be $1=5 and $2=5

5

ভেবেছিলাম যে আমি নামকরণের প্যারামিটারগুলি বাশ করতে যাওয়ার অন্য কোনও উপায়ের সাথে পাইপ করব ... রেফারেন্স দিয়ে যাচ্ছি। এটি ব্যাশ ৪.০ হিসাবে সমর্থিত

#!/bin/bash
function myBackupFunction(){ # directory options destination filename
local directory="$1" options="$2" destination="$3" filename="$4";
  echo "tar cz ${!options} ${!directory} | ssh root@backupserver \"cat > /mnt/${!destination}/${!filename}.tgz\"";
}

declare -A backup=([directory]=".." [options]="..." [destination]="backups" [filename]="backup" );

myBackupFunction backup[directory] backup[options] backup[destination] backup[filename];

বাশ ৪.৩ এর বিকল্প বিকল্প সিনট্যাক্স একটি নেমরেফ ব্যবহার করছে

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


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