Shell-Script

為什麼從函式返回時長度不同

  • July 29, 2022

你知道為什麼下面給出不同長度的數組,甚至返回它"${distro[@]}"嗎?

一個.sh

#!/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
}

"$@"

二.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

您不能從帶有echo "${distro[@]}". 它所做的只是列印到函式的標準輸出,這只是一個字節流,沒有結構,它不能將不同的數組元素分開。

實際發生的情況是,"${distro[@]}"擴展為多個不同的參數,所有參數都傳遞給echo,然後將echo它們與空格連接起來列印。實際上,它將您的三元素數組 ( redhat linux, debian linux, gentoo linux) 轉換為單個 string redhat linux debian linux gentoo linux

相應地,arr=$(get_array)也是一個標量賦值,它將stdoutget_array作為一個字元串讀取,並將其賦值給arr. (arr=( $(get_array) )將包括一個數組分配,它會服從命令替換分詞和萬用字元,並且會使用預設設置從該輸出中生成六元素數組(redhat, linux, debian…)。)


解決方法是例如每行列印一個數組元素,然後將其讀入另一端的數組中(前提是您的數組元素不包含換行符);或者將數組的名稱傳遞給內部函式並讓它在那裡儲存數據。

#!/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"

或者:

#!/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"

引用自:https://unix.stackexchange.com/questions/711720