두 개의 배열이 있습니다.
arrayA=(1 2 3)
arrayB=(a b c)
그리고 명령 줄 인수를 사용하여 그중 하나를 인쇄하고 싶습니다 if else
.
나는 성공하지 않고 구문에 대해 몇 가지 변형을 시도했다. 나는 이런 식으로하고 싶다 :
ARG="$1"
echo ${array${ARG}[@]}
그러나 “나쁜 대체”오류가 발생합니다. 어떻게하면 되나요?
답변
이것을 시도하십시오 :
$ arrayA=(1 2 3)
$ x=A
$ var=array$x[@]
$ echo ${!var}
1 2 3
노트
- 행
man bash
(파라미터 확장)
${parameter} The value of parameter is substituted. The braces are required when parameter is a positional parameter with more than one
숫자 또는 매개 변수 뒤에 이름의 일부로 해석되지 않는 문자가 오는 경우.
* 매개 변수의 첫 문자가 느낌표 (!) 인 경우 가변 간접 레벨이 도입됩니다. Bash는 나머지 매개 변수에서 형성된 변수의 값을 변수의 이름으로 사용합니다. 그런 다음이 변수가 확장되고 해당 값은 매개 변수 자체의 값이 아닌 나머지 대체에 사용됩니다. 이것을 간접 확장이라고합니다. * 이에 대한 예외는 아래 설명 된 $ {! prefix *} 및 $ {! name [@]}의 확장입니다. 느낌표는 간접적으로 도입하기 위해 즉시 왼쪽 괄호를 따라야합니다.
답변
다른 답변 에서 지적한 것처럼 간접 액세스를 사용할 수 있지만 ksh 및 Bash 4.3 이상에서 다른 방법은 nameref를 사용하는 것입니다. 특히 배열의 경우 nameref를 통해 배열을 색인 할 수 있고 참조로 사용되는 변수에 색인을 넣을 필요가 없으므로 더 유용 할 수 있습니다.
arr1=(a b c)
arr2=(x y z)
typeset -n p=arr1 # or 'declare -n'
echo "${p[1]}" # prints 'b'
간접 액세스를 통해 작동하지 않습니다.
q=arr2
echo "${!q}" # prints 'x', the same as $arr2
echo "${!q[1]}" # doesn't work, it tries to take q[1] as a reference
C 프로그래머가 말했듯이 ${!q[1]}
여기 q
에서는 배열에 대한 포인터가 아닌 포인터의 배열 인 것처럼 작동 합니다.
답변
arrayA=(1 2 3)
arrayB=(a b c)
ARG="$1"
eval echo \${array${ARG}[@]}
dataget (){
eval echo \${array${1}[${2:-@}]}
}
$ dataget A
1 2 3
$ dataget A 0
1
$ dataget B 1
b
참고 :
공간이 부족한 경우 탈출 하십시오 !
eval dostuff \"\${array${1}[${2:-@}]}\"
답변
이것은 많은 시행 착오를 겪었지만 결국 효과가있었습니다.
유스에서 영감을 얻었습니다. 그러나 다른 모든 대답은 이전 bash에 도움이되지 않았습니다 (suse11sp1 [3.2.51 (1) -release])
‘for’루프는 간접 배열 확장을 거부했습니다. 대신 사전 확장해야합니다.이를 사용하여 새 변수 이름으로 다른 배열을 만듭니다. 아래의 예는 의도 한 용도이므로 이중 루프를 보여줍니다.
THEBIGLOOP=(New_FOO New_BAR)
FOOthings=(1 2 3)
BARthings=(a b c)
for j in ${THEBIGLOOP[*]}
do
TheNewVariable=$(eval echo \${${j#New_}things[@]})
for i in $TheNewVariable
do
echo $j $i" hello"
echo
done
done
#을 사용하여 첫 번째 배열 항목에서 “New_”를 삭제 한 다음 “things”와 연결하여 “FOOthings”를 얻습니다. echo 및 eval을 사용하여 \ $ {}을 입력 한 다음, 오류를 발생시키지 않고 순서대로 수행합니다. 새 $ ()로 싸서 새 변수 이름이 지정되었습니다.
$ Test.sh
New_FOO 1 hello
New_FOO 2 hello
New_FOO 3 hello
New_BAR a hello
New_BAR b hello
New_BAR c hello
업데이트 ##### 2018/06/07
최근 에이 문제에 대한 또 다른 스핀을 발견했습니다. 생성 된 변수는 실제로 배열이 아니라 공백으로 구분 된 문자열입니다. 위의 작업은 “for”의 작동 방식으로 인해 배열이 읽히지 않고 확장 된 다음 반복됩니다. 아래 추출을 참조하십시오.
for VARIABLE in 1 2 3 4 5 .. N
do
command1
command2
commandN
done
그러나 그런 다음 배열로 사용해야했습니다. 이를 위해 한 단계 더 수행해야했습니다. Dennis Williamson이 작성한 코드를 그대로 사용했습니다 . 나는 그것을 테스트했고 잘 작동합니다.
IFS=', ' read -r -a TheNewVariable <<< ${TheNewVariable[@]}
“IFS = ‘,'”는 델리 미네 이터가 포함 된 변수입니다. “-a”와 함께 “read”는 찌르기를 자르고 배열 변수로 다시 보냅니다. 참고이 따옴표에 대한 존중이없는,하지만 몇 가지 옵션이 있습니다 읽기 이 관리는, 예를 들어 나는 것은 내가 필요하지 않았다 -r 플래그를 제거했습니다. 이제 변수 생성에이 추가 기능을 결합하여 데이터를 원하는대로 처리하고 처리 할 수 있습니다.
THEBIGLOOP=(New_FOO New_BAR)
FOOthings=(1 2 3)
BARthings=(a b c)
for j in ${THEBIGLOOP[*]}
do
IFS=', ' read -a TheNewVariable <<< $(eval echo \${${j#New_}things[@]})
for i in ${TheNewVariable[@]} #Now have to wrap with {} and expand with @
do
echo $j $i" hello"
echo ${TheNewVariable[$i]} #This would not work in the original code
echo
done
done
답변
이것이 동적으로 명명 된 변수를 만드는 방법입니다 (bash 버전 <4.3).
# Dynamically named array
my_variable_name="dyn_arr_names"
eval $my_variable_name=\(\)
# Adding by index to the array eg. dyn_arr_names[0]="bob"
eval $my_variable_name[0]="bob"
# Adding by pushing onto the array eg. dyn_arr_names+=(robert)
eval $my_variable_name+=\(robert\)
# Print value stored at index indirect
echo ${!my_variable_name[0]}
# Print value stored at index
eval echo \${$my_variable_name[0]}
# Get item count
eval echo \${#$my_variable_name[@]}
다음은 동적으로 명명 된 배열을 관리하는 데 사용할 수있는 함수 그룹입니다 (bash 버전 <4.3).
# Dynamically create an array by name
function arr() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
# The following line can be replaced with 'declare -ag $1=\(\)'
# Note: For some reason when using 'declare -ag $1' without the parentheses will make 'declare -p' fail
eval $1=\(\)
}
# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
eval $1[\$\(\(\${#${1}[@]}\)\)]=\$2
}
# Update an index by position
function arr_set() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
eval ${1}[${2}]=\${3}
}
# Get the array content ${array[@]}
function arr_get() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
eval echo \${${1}[@]}
}
# Get the value stored at a specific index eg. ${array[0]}
function arr_at() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
[[ ! "$2" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
local v=$1
local i=$2
local max=$(eval echo \${\#${1}[@]})
# Array has items and index is in range
if [[ $max -gt 0 && $i -ge 0 && $i -lt $max ]]
then
eval echo \${$v[$i]}
fi
}
# Get the value stored at a specific index eg. ${array[0]}
function arr_count() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
local v=${1}
eval echo \${\#${1}[@]}
}
array_names=(bob jane dick)
for name in "${array_names[@]}"
do
arr dyn_$name
done
echo "Arrays Created"
declare -a | grep "a dyn_"
# Insert three items per array
for name in "${array_names[@]}"
do
echo "Inserting dyn_$name abc"
arr_insert dyn_$name "abc"
echo "Inserting dyn_$name def"
arr_insert dyn_$name "def"
echo "Inserting dyn_$name ghi"
arr_insert dyn_$name "ghi"
done
for name in "${array_names[@]}"
do
echo "Setting dyn_$name[0]=first"
arr_set dyn_$name 0 "first"
echo "Setting dyn_$name[2]=third"
arr_set dyn_$name 2 "third"
done
declare -a | grep "a dyn_"
for name in "${array_names[@]}"
do
arr_get dyn_$name
done
for name in "${array_names[@]}"
do
echo "Dumping dyn_$name by index"
# Print by index
for (( i=0 ; i < $(arr_count dyn_$name) ; i++ ))
do
echo "dyn_$name[$i]: $(arr_at dyn_$name $i)"
done
done
for name in "${array_names[@]}"
do
echo "Dumping dyn_$name"
for n in $(arr_get dyn_$name)
do
echo $n
done
done
다음은 동적으로 명명 된 배열을 관리하는 데 사용할 수있는 함수 그룹입니다 (bash 버전> = 4.3).
# Dynamically create an array by name
function arr() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -g -a $1=\(\)
}
# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
declare -n r=$1
r[${#r[@]}]=$2
}
# Update an index by position
function arr_set() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
declare -n r=$1
r[$2]=$3
}
# Get the array content ${array[@]}
function arr_get() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
declare -n r=$1
echo ${r[@]}
}
# Get the value stored at a specific index eg. ${array[0]}
function arr_at() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
[[ ! "$2" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
declare -n r=$1
local max=${#r[@]}
# Array has items and index is in range
if [[ $max -gt 0 && $i -ge 0 && $i -lt $max ]]
then
echo ${r[$2]}
fi
}
# Get the value stored at a specific index eg. ${array[0]}
function arr_count() {
[[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
declare -p "$1" > /dev/null 2>&1
[[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
declare -n r=$1
echo ${#r[@]}
}
array_names=(bob jane dick)
for name in "${array_names[@]}"
do
arr dyn_$name
done
echo "Arrays Created"
declare -a | grep "a dyn_"
# Insert three items per array
for name in "${array_names[@]}"
do
echo "Inserting dyn_$name abc"
arr_insert dyn_$name "abc"
echo "Inserting dyn_$name def"
arr_insert dyn_$name "def"
echo "Inserting dyn_$name ghi"
arr_insert dyn_$name "ghi"
done
for name in "${array_names[@]}"
do
echo "Setting dyn_$name[0]=first"
arr_set dyn_$name 0 "first"
echo "Setting dyn_$name[2]=third"
arr_set dyn_$name 2 "third"
done
declare -a | grep 'a dyn_'
for name in "${array_names[@]}"
do
arr_get dyn_$name
done
for name in "${array_names[@]}"
do
echo "Dumping dyn_$name by index"
# Print by index
for (( i=0 ; i < $(arr_count dyn_$name) ; i++ ))
do
echo "dyn_$name[$i]: $(arr_at dyn_$name $i)"
done
done
for name in "${array_names[@]}"
do
echo "Dumping dyn_$name"
for n in $(arr_get dyn_$name)
do
echo $n
done
done
이 예제에 대한 자세한 내용은 Ludvik Jerabek의 동적 배열에 의한 배싱하기 를 참조하십시오.
답변
절대 안돼 🙁
배열이 그렇게 단순하면 연관 배열을 사용하십시오.
declare -A array
array[A]="1 2 3"
array[B]="a b c"
불행히도 배열이 더 복잡한 경우 (예 🙂 array=( "a b" c )
작동하지 않습니다. 그런 다음 목표에 도달하는 다른 방법에 대해 더 열심히 생각해야합니다.
답변
사용하다 eval
arrayA=(1 2 3)
ARG=arrayA
eval echo \${$ARG[@]} # equivalent to eval echo \${arrayA[@]}
# note that we escape the first '$' to prevent from
# its parameter expansion before passing it to echo