함수 반환 값

함수 반환 값

my_var=$(my_func arg1 arg2 ..)코드 예제를 볼 때 bash 함수의 반환 값이 항상 함수에 반영된 다음 사용되는 이유를 누군가 설명할 수 있습니까?

my_func ()
   {
   echo "$1 , $2, $3"
   }

my_var=$(my_func .. .. ..);

이것을 사용하는 대신 서브 쉘이 열리지 않습니다.

declare g_RV  #-- global return value for all functions

myfunc ()
   {
   g_RV="$1 , $2, $3"
   }

myfunc .. .. ..; my_var=$g_RV;

왜냐하면 저는 두 번째 방법을 사용하고 있고 어떤 경우에는 첫 번째 방법으로 실패할지 궁금하기 때문입니다. 모든 사람이 서브쉘을 열고 있기 때문에 이유가 있을 것입니다.

편집: Kusalananda 및 Paul_Pedant의 의견 덕분에
$1 디렉토리의 모든 파일을 나열하거나 $2 INT>0인 경우 재귀적으로 g_RV - LAF 함수를 사용하여 재귀 함수 호출을 추가한
다음 함수 내에서 다른 함수를 호출합니다(요청 및 함수 참조!

declare g_RV

shopt -s dotglob nullglob

#-- Recursive call with g_RV
#---------------------------
#-- call: LAF [directory STR] [recursive INT (>0 .. true, 0 .. false)]  ... List all files in a folder or inclusive all files in subfolders (recursive
LAF ()
   {
   local file files="" dir_path=$1
   if [[ ${dir_path:0:1} != "/" ]]; then dir_path=$(readlink -f "$dir_path"); fi
   
   for file in "$dir_path/"*; do
      if [[ -d $file ]]; then (($2)) && { LAF "$file"; files+=$g_RV; }                    #-- recursive call
      else files+="${file}"$'\n'; fi
      done
   g_RV=$files
   }
   
LAF "/tmp" 1; my_var1=$g_RV; echo "$my_var1";

#-- function calling other functions with g_RV
#---------------------------------------------
sum_A ()
   { 
   g_RV=$(($1+$2))
   }

sum_B()
   {
   g_RV=$(($1+$2))
   }

sum_C ()
   {
   local -i sum=0;
   sum_A 5 6; sum+=$g_RV
   sum_B 12 18; sum+=$g_RV
   g_RV=$sum
   }
  
sum_C; my_var2=$g_RV; echo "sum: $my_var2";

답변1

표준 도구 및 유틸리티는 다음과 같은 방법으로 정보를 반환합니다.표준 출력, 종료 상태(0 = 정상, 그렇지 않으면 오류)로 결과를 한정합니다. 동일한 일관적인 방식으로 사용될 수 있도록 함수는 동일한 작업을 수행해야 합니다.

귀하의 예는 모든 함수에서 반환된 단일 전역 변수를 보여줍니다. 이 접근 방식을 사용하면 복잡성이 추가되고 가독성이 떨어지지 않고는 파이프나 문자열에 함수를 삽입할 수 없습니다.

고려하다

f() { sed 's/^/> /'; }
g() { nl; }

echo try | f | g    # "     1  > try"

각 함수의 반환에 전역 변수가 있는 경우(또는 두 함수 모두 동일한 전역 변수가 있는 경우) 동일한 효과를 얻으려면 후프를 뛰어넘어야 합니다.

쉘을 실행 중이고 모든 오버헤드를 고려할 때 하위 프로세스의 수는 크게 관련이 없습니다. 속도가 필요하다면 쉘 스크립트를 작성하지 마십시오.

답변2

전역 변수 사용은 일반적으로 재사용이 불가능합니다. 다른 곳에서 사용되는 전역 변수와 이름 충돌이 있을 수 있습니다.

또한 이는 대부분의 사람들이 기능이 작동할 것으로 기대하는 표준 방식이 아닙니다.

답변3

  • 적은 코드
  • 읽기가 더 쉽다
  • 기존 방법은 오류가 발생할 가능성이 적습니다.
  • echo계산 비용이 거의 0인 내장 함수입니다.
  • Bash는 Bourne Again SHell입니다.아니요[고전적인] 프로그래밍 언어
  • 일을 수행하는 고전적인 방법은 탄력적입니다 source/.. 즉, 무슨 일이 있어도 항상 작동한다는 의미입니다.

답변4

그렇지 않다언제나그냥 해. 사실, 당신은 당신의 질문에 다른 방식으로 답했습니다!

쉘 함수는 실제로 0~255 사이의 정수로 제한되는 종료 상태를 제외하고는 아무것도 반환할 수 없으므로 그다지 유용하지 않습니다. 그런 다음 외부 변수를 사용하거나 필요한 데이터를 인쇄하고 출력을 캡처하는 옵션이 있습니다.

출력을 인쇄하고 캡처하는 데 문제가 없는 것은 아닙니다. 명령 대체로 인해 대부분의 쉘이 경험하는 성능 문제를 무시하더라도 출력이 구조가 없는 단일 문자열 또는 바이트 스트림이라는 문제가 있습니다. zsh 이외의 쉘에서는 명령 대체가 NUL 바이트를 캡처할 수 없으므로 8비트 클린 바이트 스트림도 아닙니다.

배열을 반환해야 하는 경우 외부 변수를 사용하는 것이 훨씬 간단할 수 있습니다. 고정된 이름의 변수를 사용하는 대신 namerefs를 사용하면 호출자가 반환 값에 대한 변수 이름을 전달할 수 있습니다.

예를 들어, 적절한 배열 없이는 처리하기 어려운 일부 값을 갖는 어리석은 예를 들면 다음과 같습니다.

#!/bin/bash
funnystrings() {
    declare -n _dst="$1"
    _dst[0]="foo bar"
    _dst[1]="*"
    _dst[2]=$'new\nline'
}

a=()
funnystrings a
declare -p a

마찬가지로, 입력 변수에 다른 변수 이름을 전달해야 하는 경우:

squares() {
    declare -n _src="$1" _dst="$2"
    local _i _val
    for _i in "${!_src[@]}"; do
        _val=${src[$i]}
        _dst[$i]=$(( _val * _val ))
    done
}
a=(1 2 3)
b=()
squares a b

이는 Bash에서도 실제로 작동할 수 있지만 a, b특히 squares a b쉘 간에 중첩된 지역 변수가 작동하는 방식에 이상한 점이 있을 수 있다는 점에 유의하세요. 무슨 경기를 위해 unset.

관련 정보