참조에 의한 배열 호출을 사용하는 UNIX KSH/BASH(GNU bash 4.2)

참조에 의한 배열 호출을 사용하는 UNIX KSH/BASH(GNU bash 4.2)

나는 Unix 쉘 스크립팅을 처음 접했고 내 코드는 다음과 같습니다.

  i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[i]=var
  ((i=`expr i+1`))
done
a=10
b=50
c=40
d=90
e=100
Now I wanted to print the local variables contents using array into the function

print_array
{
echo "${content[0]}"
echo "${content[1]}"
echo "${content[2]}"
echo "${content[3]}"
echo "${content[4]}"
} 

내가 원하는 배열 내용은 {a,b,c,d,e}이고 a,b,c,d,e라는 로컬 변수가 있고 일부 할당된 값이 있습니다. The를 사용하여 이러한 로컬을 인쇄하고 싶습니다. 변수 배열의 이름, 배열 요소와 지역 변수 요소의 이름이 동일하므로 $와 array_names를 다양하게 조합하여 참조 호출을 시도했지만 작동하지 않았습니다.

답변1

그래서 먼저 간접인쇄 기능을 정의하는데...

_print() while [ "$#" -ne 0 ]
         do    printf '$%s = %d\n' \
                       "$1" "$(($1))"
               shift
         done

다음으로 배열을 설정하고 증분하겠습니다.

arr=( a b c d e ); i=0
for var in "${arr[@]}"
do  : "$(($var=(i+=10)))"
done

따라서 이제 값은 $a10과 $b20 등이 됩니다. 드디어 인쇄만 남았네요...

_print "${arr[@]}"

...표준 출력으로 인쇄...

$a = 10
$b = 20
$c = 30
$d = 40
$e = 50

$((이 모든 것은 쉘이 수학 확장을 처리하는 방식 때문에 작동합니다 )). 기본적으로는 evals입니다. 산술 확장에서는 쉘첫 번째확장하다어느수학을 시도하기 전에 다른 효율적인 쉘 확장을 수행하십시오. 실제 수학을 마지막 작업으로 만드십시오.

이는 다음을 의미합니다.

i=a a=10; echo "$(($i))" 

인쇄된 결과는 10쉘이 $iget의 값을 확장한 a다음 이를 평가하기 때문입니다.저것결과는 정수로 참조됩니다.

위 코드는 모든 POSIX 호환 셸에서 실행될 수 있습니다.

그러니까 나도 아마 그랬을 거라는 뜻이겠지...

i=10
for var in a b c d e
do  arr[($var=i*${#arr[@]}+i)/i]=$var
done

$var[...이름이 지정된 쉘 배열(이를 지원하는 쉘에서)의 인덱스 ]대괄호는 수학 표현식의 확장 대괄호와 동일하기 때문에 배열 할당, 인덱스 평가 및 정수 할당을 동시에 처리합니다 $((.))

명령에 포함된 위 코드를 실행하면 ksh -xc다음 디버그 출력이 표준 오류로 인쇄됩니다.

+ arr[1]=a
+ arr[2]=b
+ arr[3]=c
+ arr[4]=d
+ arr[5]=e

거기에서 나는 할 수 있습니다 :

echo "$((${arr[1]}))"
echo "$((a))"

...인쇄...

10
10

...이름이 지정된 배열을 지원하는 셸에서 동일하게 평가하기 때문입니다. 그러나 아니...

echo 'arr=(a b c d e)' | bash -x
+ arr=(a b c d e)     #bash traces the successful command to stderr
echo 'arr=(a b c d e)' | sh -x
sh: 1: Syntax error: "(" unexpected   #sh traces something else

그래서 _print()함수에서 나는 shift위치 인수를 넣었습니다.(진정한 휴대용 쉘 "$@"배열을 나타냄)어떤 것이 있지만 printf...

  1. $먼저 달러 기호 가 있습니다 .
  2. 그런 다음 첫 번째 위치 매개변수 %s에 문자열 값을 저장합니다 .$1
  3. =그 다음에는 등호가 있습니다 .
  4. 마지막으로 값을 저장합니다.값은 다음 위치에 저장됩니다.$(($1))첫 번째 위치 매개변수입니다.

함수 shift의 인수가 사라지면 위치 인수 $#개수가 0이 되고 함수가 반환될 때까지 첫 번째 위치 인수가 다음 위치 인수로 계속 대체됩니다.

함수를 실행하기 전에 배열과 간접 변수를 초기화하면 다음과 같이 작동합니다.

  • for var in "${arr[@]}"

    • [@]쉘은 다음으로 확장됩니다 .목록매개변수와 [*]이 목록의 단일 연결입니다. 확장자가 참조되지 않는 경우가능한[*]또한 완료 시 값이 있는지 여부와 현재 파일 이름 확장이 어떻게 구성되어 있는지 에 따라 목록으로 확장되지만 이렇게 하면 원하는 방식으로 작동하지 않을 수 있습니다.$IFSset -f
  • : "$(($var=(i+=10)))"

    • 의 각 값은 차례로 ${arr[@]}해당 값에 할당됩니다. 그런 다음 확장$var$(($var=(i+=10)))첫 번째$varlike 의 값에 대해 $((a=(i+=10)))마지막에 모든 계산을 수행합니다. 먼저 $i10씩 증가한 다음 값을 에 할당 $i합니다 $a.

답변2

노력하다

#i=0
for var in 'a' 'b' 'c' 'd' 'e'
do
  content[${#content[*]}]=$var  # or content[i++]=$var
done
# or just content=( 'a' 'b' 'c' 'd' 'e' )
a=10
b=50
c=40
d=90
e=100
for i in "${#content[@]}"
do
  echo ${!i}
done

답변3

내가 올바르게 이해했다면 변수 액세스에 대한 간접 참조가 필요합니다 bash. 예를 들어 다음 코드를 사용하면 됩니다.

content=( a b c d e )

a=10
b=50
c=40
d=90
e=100

echo "${!content[0]}"
echo "${!content[1]}"
echo "${!content[2]}"
echo "${!content[3]}"
echo "${!content[4]}"

당신은 다음과 같은 것을 얻을 것입니다 :

10
50
40
90
100

여기서 핵심은 bash구체적인 변수 확장 접근 방식 이다 "${! ... }".

관련 정보