2014-11-20 2 views
2

다른 배열에 다른 이름을 가진 3 개의 비슷한 파일을 읽으려고합니다. 왜냐하면 나는 불필요한 코드를 사용하고 싶지 않았기 때문에 배열 이름을 params로 받아들이는 함수를 만들려고하는데, 'command not found'오류가 발생합니다.변수 이름을 매개 변수로 전달하여 bash에서 작동

hello.sh 파일 코드 :

#!/bin/bash 
declare -a row_1 
declare -a row_2 
declare -a row_3 


load_array() 
{ 
ROW="$2" 
let i=0 
while read line; do 
    for word in $line; do 
    $ROW[$i]=$word   
((++i)) 
    done 
done < $1 
} 

load_array $1 row_1 
load_array $2 row_2 
load_array $3 row_3 

와 터미널에서이 파일을 호출 : 오류가 난 점점 오전의 sh hello.sh 1.txt 2.txt 3.txt

목록 : 할당 구문에서

hello.sh: line 13: row_1[0]=9: command not found 
hello.sh: line 13: row_1[1]=15: command not found 
hello.sh: line 13: row_1[2]=13: command not found 
hello.sh: line 13: row_2[0]=12: command not found 
hello.sh: line 13: row_2[1]=67: command not found 
hello.sh: line 13: row_2[2]=63: command not found 
hello.sh: line 13: row_3[0]=75: command not found 
hello.sh: line 13: row_3[1]=54: command not found 
hello.sh: line 13: row_3[2]=23: command not found 
+0

BashFAQ # 6은이 질문의 많은 변종에 대한 주제에 : http://mywiki.wooledge.org/BashFAQ/006 –

답변

1

를, 무엇이다 등호의 왼쪽에는 변수 이름 (스칼라에 할당 할 때) 또는 변수 이름 뒤에 대괄호로 묶인 단어가 있어야합니다 (배열 ele에 할당 할 때). 멘토). 코드에서 $ROW[$i]=$word은이 구문과 일치하지 않습니다 (시작 부분에 $이 있으므로 할당 일 수는 없습니다). 이 문자는 문자 =을 포함하는 단어 일뿐입니다.

bash에서는 내장 변수 declare을 사용하여 이름이 변수 확장과 같은 계산의 결과 인 변수에 할당 할 수 있습니다. 직선 할당과 달리 값 부분 주위에 큰 따옴표가 필요하므로 단어 분할 및 파일 이름 확장이 $word에 발생하지 않도록하십시오. 함수에서 지정을 수행하고 함수가 반환 된 후에도 값을 유지하려면 옵션 -g을 전달하십시오. 당신이 declare -g이없는 bash는 이전 버전을 실행하는 경우

declare -g $ROW[$i]="$word" 

대신 eval를 사용할 수 있습니다. 이것은 평범한 sh에서 동적으로 명명 된 변수에 할당하는 데 사용할 방법입니다. 인용문을 올바르게 처리하십시오 (예 : ROW). row_1이면 eval의 인수로 전달 된 문자열은 row_1[$i]=$word (구문 분석 및 실행을위한 셸 명령)이어야합니다.

eval "$ROW[\$i]=\$word" 
+0

선언의이 종류는 만드는 것 같다 로컬 과제와 전역에서 선언 된 값을 사용할 수 없습니다. 이것은 내가 얻는 변수의 에코입니다 : http://i.imgur.com/SSUNWL.png – user2816626

+0

@ user2816626 아, 미안하지만, 나는 당신이 함수 밖의 값을 필요로한다는 것을 눈치 채지 못했습니다. '-g' 옵션을 추가하십시오 (제 편집 참조). – Gilles

+0

그것은 훌륭한 해결책입니다. 나는 전에 그것을 보지 못했다. 나는 당신이'eval' 또는'$ {! ROW}'형 구조를 사용해야 만했을 것이라고 추정했을 것입니다. 학습이 발생했습니다. –

0

구문 따라서 인 (4.3 떠들썩한 파티) 현대와이를위한 이상적인 방법 :

load_array() { 
    declare -n _load_array__row=$2 
    declare -a _load_array__line 
    _load_array__row=() 
    while read -r -a _load_array__line; do 
    _load_array__row+=("${_load_array__line[@]}") 
    done <"$1" 
} 

(변수 이름은 호출 함수와의 충돌 가능성을 줄일 홀수이고; 다른 예를 들어 대상을 설명하는 데 전역 변수가 아닌 지역 변수를 참조 할 때 ROW 또는 line이라는 변수에 콘텐츠를로드하라는 메시지가 표시되면 답변에 문제가 발생합니다.


bash는 3.2 (애플에 의해 제공되는 고대 자료), 내부 루프와 관련된 성능 저하를 방지하고 글로브 확장과 관련된 버그와 호환 유사한 메커니즘 (참조 원래 코드는 *를 포함하는 라인에 무엇을 !) 다음 :

load_array() { 
    local -a _load_array__array=() 
    local -a _load_array__line 
    while read -r -a _load_array__line; do 
    _load_array__array+=("${_load_array__line[@]}") 
    done <"$1" 
    eval "$2=(\"\${_load_array__array[@]}\")" 
} 
관련 문제