Bash +戻りスタック



問題
bashが多くの特異性を持つと言うのは控えめです.最も厄介なことの1つは、副シェルで関数を呼び出すことなく関数から整数の他に何かを返す明白な方法の欠如です.

部分殻
subshellという用語は、bash fork ()が子プロセスであることを意味します.マルチプロセスアプリケーションを作成する場合は、これは素晴らしい機能です.関数から複雑な戻り値を取得したい場合は、これはマゾヒズムの運動になります.

複素リターン値
再び:サブシェルを呼び出すことなく、任意のbash関数から整数を返すことができます問題は他の何かを返すことである.
関数の結果を中継する1つの方法は、グローバル変数に格納し、関数が戻った後に取得します.この目的のために専用の一つのグローバル変数が再帰の簡単な実装を排除するか、1つ以上の値を返すどんな機能も持たないので、この戦略に対する多くの即時の魅力はありません.

スタックを返す
スタックは永遠にコンピューティングに使用されている.bashの1つを実装するだけで77間隔の行を取る.最初に、このスタックに使用できるグローバル配列が必要です.
# Global array to use as a return stack
declare -g -a __RTN_STK
名前空間衝突を避けるために主要なアンダースコアに注目してください.次に、このスタックに物をプッシュする方法が必要です.Bashは関数プロトタイプについてはカジュアルなので、どのように多くの項目をスタックにプッシュするかを決めるために、呼び出し元に任せます.
function RTN_push
############################################################
# Use this to push things onto the global return stack
# Arguments:
#    Whatever strings you wish placed on the stack
#
{
   # Necessary to avoid "unbound variable" exception for empty stack
   local OPTS=$(shopt -o -p nounset errexit)
   set +ue

   # For readability, store array index value here before using
   local -i ndx

   # Push arguments onto the stack
   while [[ -n "$1" ]]; do

      # Array index is current size of array
      ndx=${#__RTN_STK[@]}

      # Place argument onto stack
      __RTN_STK[$ndx]="$1"

      # Discard argument from argv
      shift

   done

   # Restore options
   eval $OPTS
}
優れた.では、値をスタックからポップする方法が必要です.
function RTN_pop
############################################################
# Use this to pop things off of the return stack
# Arguments:
#    Names of global varibles to be loaded by popping
#    strings from the stack.
#
{
   # Necessary to avoid "unbound variable" exception
   local OPTS=$(shopt -o -p nounset)
   set +u

   local -i arg ndx
   for (( arg= $#; arg ; --arg )); do
      ndx=${#__RTN_STK[@]}
      (( --ndx ))
      eval ${!arg}="\${__RTN_STK[\$ndx]}"
      # pop from stack, free memory
      unset __RTN_STK[$ndx]
   done

   # Restore options
   eval $OPTS
}

最後に、この方法の使用例を示します.
#!/bin/bash
############################################################
# Example script to demonstrate a function which returns
# multiple objects without the use of subshells
#
# John Robertson <[email protected]>
# Initial release: Thu Sep 10 11:58:23 EDT 2020
#

# Halt on error, no globbing, no unbound variables
set -efu

# import return stack tools
source ../bash++

function returns_3_strings ()
#######################################################
# Example function with 3 returns objects
# Arguments:
#   none
# Returns:
#  3 strings
#
{
   RTN_push 'string #1' 'string #2' 'string #3'
}

###################################
### Execution starts here #########
###################################

# NOTE: We'll reserve R1 R2 R3 ... global
# variables to fetch return values from
# return stack.

# Call our function
returns_3_strings

# Pop the results into global return "registers"
RTN_pop R1 R2 R3

# print the results
echo "R1= '$R1', R2= '$R2', R3= '$R3'"
... 結果
R1= 'string #1', R2= 'string #2', R3= 'string #3'
この記事で参照される両方のファイルは、Githubで利用できます!