Bash ශ්‍රිතයකට පරාමිතීන් පසු කිරීම


1012

මම උත්සාහ කරන්නේ බාෂ් ශ්‍රිතයක පරාමිතීන් සමත් වන්නේ කෙසේදැයි සෙවීමට ය, නමුත් ඉදිරියට එන්නේ සෑම විටම විධාන රේඛාවෙන් පරාමිතිය සම්මත කරන්නේ කෙසේද යන්නයි.

මගේ ස්ක්‍රිප්ට් තුළ පරාමිතීන් සම්මත කිරීමට මම කැමතියි. මම උත්සාහ කළා:

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

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

නමුත් වාක්‍ය ඛණ්ඩය නිවැරදි නොවේ, මගේ ශ්‍රිතයට පරාමිතියක් ලබා දෙන්නේ කෙසේද?


8
"... නමුත් එන්නේ සෑම විටම විධාන රේඛාවෙන් පරාමිතිය සම්මත කරන්නේ කෙසේද යන්නයි" - ඔව්! එයට හේතුව Bash ස්ක්‍රිප්ට් මූලික වශයෙන් විධාන රේඛාවල අනුක්‍රමයයි - විධාන රේඛාවේ විධානයක් සේම Bash ස්ක්‍රිප්ට් එකක ශ්‍රිතයක් ක්‍රියාත්මක කරන්න! :-) ඔබේ ඇමතුම myBackupFunction ".." "..." "xx"; වරහන් නොමැත, කොමාව නැත.
විල්

4
මෙම ප්‍රශ්නයට ප්‍රතිවිරුද්ධ කොටස: බැෂ් ශ්‍රිතයකින් ප්‍රතිලාභ අගය
MSalters

Answers:


1660

ශ්‍රිතයක් ප්‍රකාශ කිරීමේ සාමාන්‍ය ක්‍රම දෙකක් තිබේ. මම දෙවන ප්‍රවේශයට කැමතියි.

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 ශත: ෂෙල් නිර්මාණය කරන දී මූලාශ්ර බව ගොනුව වාසය (තිත්) අවශ්ය වූ විට, මම භාවිතා කිරීමට කැමති බවත් functionඉඟි පද සහ එම (). මගේ ඉලක්කය (ගොනුවක, විධාන රේඛාවක් නොවේ) පැහැදිලිකම වැඩි කිරීම, ටයිප් කළ අක්ෂර ගණන අඩු නොකිරීම, එනම් function myBackupFunction() compound-statement.
ටෙරී ගාඩ්නර්

23
@CMCDragonkai, functionයතුරු පද අනුවාදය දිගුවකි; අනෙක් පෝරමය සියලුම පොසික්ස් අනුකූල ෂෙල් වෙඩි තුළ ක්‍රියා කරයි.
චාල්ස් ඩෆි

9
Er ටෙරීගාඩ්නර්, පැහැදිලිකම වැඩි කිරීමට ඔබ ගන්නා උත්සාහයන් අනුකූලතාව අඩු කරන බව සලකන්න.
චාල්ස් ඩෆි

7
On රොන්බර්ක්, සමහර විට - නමුත් අප පැහැදිලි බව පමණක් සලකා බැලුවද, functionපැරණි ksh- පවුලේ ෂෙල් වෙඩි වල මූලික පදය සහතික කර ඇති අතර එය නූතන බාෂ් ගෞරව නොකරන බව හඳුන්වා දුන්නේය (එවැනි ෂෙල් වෙඩි වලදී functionදේශීයව පෙරනිමියෙන් විචල්‍යයන් ඇති කළේය; , එය එසේ නොවේ). එනිසා, එහි භාවිතය ksh හැසිරීම දන්නා සහ අපේක්ෂා කළ හැකි ඕනෑම කෙනෙකුට පැහැදිලි බව අඩු කරයි. Wiki.bash-hackers.org/scripting/obsolete
චාල්ස් ඩෆි

72

ඉහළ මට්ටමේ ක්‍රමලේඛන භාෂා පිළිබඳ දැනුම (සී / සී ++ / ජාවා / පීඑච්පී / පයිතන් / පර්ල් ...) ගිහියාට යෝජනා කරනුයේ එම වෙනත් භාෂාවල මෙන් බැෂ් කාර්යයන් ක්‍රියාත්මක විය යුතු බවයි. ඒ වෙනුවට , බැෂ් ශ්‍රිතයන් ෂෙල් විධාන මෙන් ක්‍රියා කරන අතර, ෂෙල් විධානයකට විකල්පයක් ලබා දිය හැකි ආකාරයටම තර්ක ඔවුන් වෙත ලබා දෙනු ඇතැයි අපේක්ෂා කරයි (උදා ls -l). ඇත්ත වශයෙන්ම, bash හි ක්‍රියාකාරී තර්ක ස්ථානීය පරාමිතීන් ලෙස සලකනු ලැබේ ( $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[@]}"

65

ඔබ නම් කරන ලද පරාමිතීන් කැමති නම්, (උපක්‍රම කිහිපයක් සමඟ) ඇත්ත වශයෙන්ම නම් කරන ලද පරාමිතීන් ශ්‍රිත වෙත යැවිය හැකිය (අරා සහ යොමු යොමු කිරීමට ද එය සමත් වේ).

මා විසින් සකස් කරන ලද ක්‍රමය මඟින් මෙවැනි ශ්‍රිතයකට නම් කරන ලද පරාමිතීන් නිර්වචනය කිරීමට ඉඩ ලබා දේ:

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

වෙනත් වචන වලින් කිවහොත්, ඔබට ඔබේ පරාමිතීන් ඔවුන්ගේ නම් වලින් ඇමතිය හැකිවා පමණක් නොව (එය වඩාත් කියවිය හැකි හරයක් සෑදී ඇත), ඔබට සැබවින්ම අරා පසු කළ හැකිය (සහ විචල්‍යයන් සඳහා යොමු කිරීම් - මෙම අංගය ක්‍රියාත්මක වන්නේ 4.3 හි පමණක් වුවද)! ප්ලස්, සිතියම්ගත කළ විචල්‍යයන් සියල්ලම ඩොලර් 1 (සහ වෙනත්) මෙන් දේශීය විෂය පථයේ ඇත.

මෙම කාර්යය කරන කේතය ඉතා සැහැල්ලු වන අතර එය bash 3 සහ bash 4 යන දෙකින්ම ක්‍රියා කරයි (මේවා මා විසින් අත්හදා බැලූ එකම අනුවාදයන් වේ). ඔබ මේ වගේ තවත් උපක්‍රම ගැන උනන්දුවක් දක්වන්නේ නම් එය වඩාත් හොඳ සහ පහසු කරවයි, ඔබට මගේ Bash Infinity Framework දෙස බැලිය හැකිය , පහත කේතය එහි ක්‍රියාකාරීත්වයන්ගෙන් එකක් ලෙස ලබා ගත හැකිය.

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
නියම පිළිතුර! මම දැන් Bash Infinity පිළිබඳ පර්යේෂණ කළ අතර එය සැබවින්ම ප්‍රයෝජනවත් වනු ඇති බව පෙනේ. ස්තූතියි!
ජොනතන් හල්ට්

ස්තූතියි on ජොනතන් හල්ට්! මම ඇත්ත වශයෙන්ම මෑතකදී මගේ ඉහත පිළිතුර යාවත්කාලීන කර ඇති අතර, එය දැන් Bash Infinity 2.0 හි ඇති කේතයට අළුත්, නැවත ලිවූ කේතයකි. මා එය නැවත ලිවීමට හේතුව පැරණි ක්‍රියාත්මක කිරීමේ දෝෂයකි (එය GitHub හි ඇති ගැටළු වල). නව අනුවාදය නැවත Bash Infinity වෙත ඒකාබද්ධ කිරීමට කාලය නොමැති වී තිබේ. එය ප්‍රයෝජනවත් වී ඇති බව දැනගැනීමට ලැබීම සතුටක්.
niieani

හායි ඉනියානි, මම ඔබේ පිළිතුරෙහි භාවිතා කරන ස්වරූපයෙන් බැෂ් ශ්‍රිතයක් නිර්මාණය කිරීමට උත්සාහ කරන විට එය මට පවසන්නේ උචිත ලෙස ucommon utils ස්ථාපනය කළ යුතු බවයි. ඔබේ බැෂ් ස්ක්‍රිප්ට් එක ක්‍රියා කරන්නේ කෙසේද? මම මෙය නිවැරදිව කරනවාද? මම ඔබව තේරුම් ගත්තා නම් හෝ වෙනත් අයෙකු මූලික වශයෙන් ucommon util වැඩසටහන ගොඩනඟා ඇත්තේ Bash දීර් extension කිරීම සඳහා ඉඩ දීමට නම්, හරිද?
ඩේවිඩ් ඒ. ප්‍රංශ

@ ඩේවිඩ්ඒ. ෆ්‍රෙන්ච් නැත, මෙය සිදු නොවිය යුතුය. ucommonමගේ කේතය අතර කිසිදු සම්බන්ධයක් නොමැත . ඔබ සඳහන් කළ ගැටලුවට හේතු වන යම් මෙවලමක් ඔබ විසින් ස්ථාපනය කර ඇති අතර එය කුමක් විය හැකිදැයි නොදැන.
niieani

27

පාරෙන් සහ කොමාව අතපසු කරන්න:

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

ශ්‍රිතය මේ ආකාරයට විය යුතුය:

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

9

මෙම උදාහරණය ඔබට උපකාරී වනු ඇතැයි මම බලාපොරොත්තු වෙමි. එය පරිශීලකයාගෙන් අංක දෙකක් ගෙන, 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' සහ y සඳහා 'x' ඇතුළත් කිරීමට උත්සාහ කරන්න, එවිට එය එකතු වන බව ඔබට පෙනෙනු ඇත (x + y) = (5 + x) = (5 + 5) = 10. අනෙකුත් සියලුම භාවිත අවස්ථා සඳහා ඔබේ උදාහරණය අසාර්ථක වනු ඇත. ඒ වෙනුවට ඔබ සාමාන්‍ය කේතය සඳහා 'add "$ x" "$ y" භාවිතා කළ යුතුය.
විල්

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

නම් කරන ලද පරාමිතීන් කඩාවැටීමට වෙනත් ක්‍රමයක් ගැන සඳහන් කරමින් මම නල මාර්ගයක් ගැන සිතුවෙමි. බාෂ් 4.0 අනුව මෙය සහාය වේ

#!/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];

Bash 4.3 සඳහා විකල්ප වාක්‍ය ඛණ්ඩයක් වන්නේ nameref භාවිතා කිරීමයි

නාමපදය බාධාවකින් තොරව විකෘති වන තරමට වඩා පහසු වුවද, සමහර පැරණි සහාය දක්වන ඩිස්ට්‍රෝ තවමත් පැරණි අනුවාදයක් නැව්ගත කරයි, එබැවින් මම එය තවම නිර්දේශ නොකරමි.


“පයිප්පයක්”. ඔබ එහි කළ දේ මට පෙනේ!
ජැක්ටෝස්
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.