함수에서 반환할 때 길이가 다른 이유는 무엇입니까?

함수에서 반환할 때 길이가 다른 이유는 무엇입니까?

다음이 길이가 다른 배열을 제공하고 심지어 로 반환하는 이유를 알고 계십니까 "${distro[@]}"?

금연 건강 증진 협회

#!/bin/bash

. ./two.sh
    
hello(){
  arr=$(get_array)
  echo "Length arr:" "${#arr[@]}" # array is not preserved and returns 1, but why?
  show_length # returns length as correct 3
}

"$@"

2.sh

#!/bin/bash

get_array(){
  distro=("redhat linux" "debian linux" "gentoo linux")
  echo "${distro[@]}"
}

show_length(){
  distro=("redhat linux" "debian linux" "gentoo linux")
  echo "Length distro:  ${#distro[@]}"
}

왜:

sh ./one.sh hello
Length arr: 1
Length distro:  3

답변1

가 있는 함수에서는 배열을 반환할 수 없습니다 echo "${distro[@]}". 그것이 하는 일은 함수의 표준 출력으로 인쇄하는 것뿐입니다. 이는 구조가 없는 바이트 스트림일 뿐이며 다른 배열 요소를 분리할 수 없습니다.

실제로 일어나는 일은 "${distro[@]}"여러 가지 매개변수로 확장되어 모두 에 전달된 echo다음 echo인쇄되고 공백과 연결된다는 것입니다. 효과적으로 3개 요소 배열( redhat linux, debian linux, gentoo linux)을 단일 문자열로 변환합니다 redhat linux debian linux gentoo linux.

이에 따라 stdout을 문자열 로 읽고 .( 배열 할당이 포함되며 기본 설정을 사용하여 생성된 토큰화 및 와일드카드에 대한 명령 대체가 적용됨)에 할당 arr=$(get_array)하는 스칼라 할당도 있습니다.get_arrayarrarr=( $(get_array) )여섯 가지 요소이 출력의 배열( redhat, linux, debian, linux, gentoo, ) 입니다. linux)


해결 방법은 개행 문자를 구분 기호로 사용하여 배열 요소를 인쇄한 다음 일반 토큰화보다 더 스마트한 방법을 사용하여 반대쪽 배열로 읽는 것입니다.이름배열을 내부 함수에 전달하고 그 안에 데이터를 저장하도록 합니다.

readarray(Bash 4.0 기준)을 사용하여 한 줄에 하나의 값을 인쇄합니다.

#!/bin/bash
foo() {
    local arr=("foo bar" "doo")
    printf "%s\n" "${arr[@]}"
}
readarray -t arr2 < <(foo)
printf "read %d elements: " "${#arr2[@]}"
printf "<%s> " "${arr2[@]}"
printf "\n"

그러나 배열이 비어 있으면 printf개행 문자가 계속 인쇄되고 반대쪽 끝의 결과는 요소 배열이 됩니다.

또는 NUL 바이트를 구분 기호로 사용하여(Bash 4.4부터) 임의의 배열 요소를 전달하고 빈 배열 문제를 해결할 수 있습니다.

#!/bin/bash
foo() {
    local arr=("foo bar" $'new\nline')
    if (( ${#arr[@]} )); then
        printf "%s\0" "${arr[@]}"
    fi
}
readarray -t -d '' arr2 < <(foo)
# use declare -p for unambiguous shell-quoted output
declare -p arr2   

또는 변수 이름을 전달하여 nameref를 사용하세요.

#!/bin/bash
bar() {
    local arr=("foo bar" "doo")
    declare -n _name="$1"
    _name=("${arr[@]}")
}
bar arr2
printf "got %d elements: " "${#arr2[@]}"
printf "<%s> " "${arr2[@]}"
printf "\n"

관련 정보