루프를 사용하여 함수를 호출 for
하고 반환 값을 변수에 저장합니다. 코드를 실행하면 command not found
오류가 발생합니다. 뭐가 문제 야?
#!/bin/bash
check_1()
{
x_$1=$(check_2 $1)
}
check_2()
{
ans=$((3+$1))
echo $ans
}
for((i=1; i<=2;i++))
do
check_1 $i
tmp=x_$i
echo ${!tmp}
done
위 스크립트를 실행하면 다음과 같은 결과를 얻습니다.
sample.sh: line 5: x_1=4: command not found
sample.sh: line 5: x_2=5: command not found
답변1
이 방법으로는 변수 이름을 정의할 수 없습니다. 다른 변수의 값을 사용하여 변수 이름을 구성하려고 하는데 x_$1=foo
작동하지 않습니다. 더 좋은 방법은 배열을 사용하는 것입니다.
#!/bin/bash
check_1()
{
x[$1]=$(check_2 "$1")
}
check_2()
{
ans=$((3+$1))
echo "$ans"
}
for((i=1; i<=2;i++))
do
check_1 "$i"
echo "${x[$i]}"
done
위의 결과는 다음과 같습니다.
$ sample.sh
4
5
답변2
Tedden이 말한 대로 해야 합니다.그의 대답, 대신 bash의 연관 배열을 사용하십시오.
그러나 당신이 주장하고 충분히 새로운 bash를 가지고 있다면 다음을 사용할 수 있습니다.이름 참조(그런데 이것은 매뉴얼 페이지에서 검색할 수 있는 마법의 단어입니다.)
i=1
declare -n tmp="foo_$i" # this is the nameref line
tmp="fooval" # actually sets $foo_1
echo "$foo_1" # prints fooval
함수 내부에 있는 경우 함수 로컬 변수를 가져오는 local -n
대신 사용하세요.declare -n
답변3
수학만 공부하지 않는다면 제가 추천하고 싶은 유일한 것은안전하고 휴대 가능나는 매우 엄격한 테스트가 필요하지 않은 방법을 알고 있습니다.
var1=string1
export "$var1=string2"
echo "$var1"
echo "$string1"
산출
string1
string2
그러나 수학을 수행하는 중이므로 문제는 echo
변수를 정의하고 동시에 현재 셸에서 평가해야 할 때 변수의 값을 하위 셸에 넣는다는 것입니다.
i=0 ; until [ $((i=$i+1)) -ge 3 ]
do echo "\$x_$i = $((x_$i=3+$i))"
done
echo $x_1 $x_2
산출
$x_1 = 4
$x_2 = 5
4 5
그래서 당신이 하는 일은 수학뿐입니다. 쉘 연산의 흥미로운 점은 이를 사용하여 현재 쉘의 변수를 하위 쉘 없이 두 번 안전하게 평가할 수 있다는 것입니다.
산술 확장은 산술 표현식을 평가하고 해당 값을 바꾸는 메커니즘을 제공합니다. 산술 확장의 형식은 다음과 같습니다.
$((expression))
표현식은 큰따옴표로 묶인 것처럼 처리되어야 하지만 표현식 내의 큰따옴표는 특별히 처리되지 않습니다. 쉘은 매개변수 확장, 명령 대체 및 따옴표 제거를 위해 표현식의 모든 토큰을 확장해야 합니다.
아마도 더 흥미롭게도 다음과 같이 말합니다.
산술 표현식의 변수에 대한 모든 변경 사항은 매개변수 확장과 같은 산술 확장 후에 적용되어야 합니다
"${x=value}"
.쉘 변수에
x
유효한 정수 상수(선택적으로 선행 플러스 또는 마이너스 기호 포함)를 형성하는 값이 포함되어 있는 경우 산술 확장 합계는 동일한 값을 반환"$((x))"
해야 합니다 ."$(($x))"
따라서 산술 대체 컨텍스트에서 변수가 정의된 경우 해당 정의는 현재 환경에서 유지됩니다. 좋다:
echo $((x=1)); echo $x
1
1
하지만 다른 부분을 추가하면 - 특히셸은 모든 태그를 확장해야 합니다. 그리고저것"$((x))"
"$(($x))"
동일한 값을 반환해야 합니다 .. 위의 루프가 어떻게 작동하는지 확인할 수 있습니다 until
.
그래서:
$((x_ #just a string
$i #integer value
= #assignment operator
3 + #addition
$i )) #same integer value
쉘은 $i
할당 연산자 앞의 문자열인 변수 쉘 토큰과 합계가 할당되는 정수 값에 대해 수행되는 추가 연산이라는 두 가지 컨텍스트에서 확장 되어야 함을 알 수 있습니다 x_$i
.
배열은 편리할 수 있지만 한 가지 형식을 제외하면 이식성이 없으며 구현에 따른 혼란이 따릅니다. 또한 - 귀하가 요청한 질문에 대한 답변은 다음과 같습니다.
이것이 바로 다음 기능이 작동하는 이유입니다.
defv() {
[ -n "${1##*[!0-9]*}" ] && # verify $1 is numeric only
v=x_$1 && # redefine caller loop var
: $((x_$1=5+$1)) # : do nothing but expand arg
}
for v in 1 2 3 4 5 # init array
do defv $v # defv() $indirection
echo "$v = $(($v))" # \$x_$indirection = $x_$indirection
done
산출
x_1 = 6
x_2 = 7
x_3 = 8
x_4 = 9
x_5 = 10
귀하의 기능:
check_1()
{
check_2 x_$1 $1
}
check_2()
{
: $(($1=3+$2))
}
for((i=1; i<=2;i++))
do
check_1 $i
tmp=x_$i
echo ${!tmp}
done
산출
4
5