bash: 인덱스를 저장하여 함수에 대한 매개변수의 배열 이름을 가져옵니다.

bash: 인덱스를 저장하여 함수에 대한 매개변수의 배열 이름을 가져옵니다.

선택한 요소의 색인을 표시하는 기능이 있습니다. 배열 이름으로 사용하기 위해 함수에 매개변수를 전달하려고 합니다. 이것은 작동합니다:

getIndex() {
arrname=$1[@]
b=("${!arrname}")
index=1; while ((index<${#b[@]})); do
    if [[ "${b[$index]}" = "$VALUE" ]]; then
        echo "index is $index"; return
    fi  
        ((index++)); done

}

하지만 이 함수에 이름을 전달한 배열에는 첫 번째 요소의 인덱스로 인덱스 1이 있습니다(줄 번호와 유사한 인덱스를 가지려면 이 인덱스가 필요하며, 이 인덱스에서 배열의 패턴을 얻습니다.

a=1
while read line; do
    if [[ $line =~ ^[0-9] ]]; then
        avg[$a]=`echo $line | awk '{print $6}'`
        ((a++));    
    fi

그리고 getIndex() 함수를 실행하면 배열의 첫 번째 요소는 인덱스 0에서 시작됩니다.

따라서 질문은 다음과 같습니다. 배열의 인덱스를 저장하는 기능을 수행하기 위해 매개변수에 배열 이름을 전달할 수 있는 방법이 있습니까? 아니면 그냥 잊어버리고 함수 응답에 +1을 추가해야 할 수도 있습니다.

답변1

다음 구성을 사용하고 있습니다.

b=("${!arrname}")

이는가치배열의 다음을 b[]사용 하여 새 배열을 만듭니다.bash 기본 배열 인덱스는 0부터 시작합니다.. 배열의 복사본을 적절하게 초기화하려면 인덱스를 복원해야 합니다(예: eval출력을 구문 분석하거나 -ing하여 declare -p arrname).

복사하는 것보다 더 나은 접근 방식은인덱스값 대신 이를 사용하여 배열을 반복합니다. 이 접근 방식은 희박하거나 0이 아닌 기반의 표준 배열(및 bash4 연관 배열)에서도 작동합니다.

문제점(항상 존재하는 것은 아님)은 !이중 의무를 수행한다는 것입니다. 간접 참조에서의 사용은 ${!name}배열 인덱스 확장에 대한 사용과 호환되지 않으므로 ${!arrname[@]}을 사용해야 합니다 eval.

이를 구현하는 수정된 버전은 다음과 같습니다.

getIndex2() {
  local arrname=$1 iidx idxs index ival val
  printf -v iidx '"${!%s[@]}"' "$arrname"
  eval "idxs=($iidx)"
  for index in "${idxs[@]}"; do
    printf -v ival '${%s[%s]}' "$arrname" "$index"
    eval "val=$ival"
    if [[ "${val}" = "$VALUE" ]]; then
        echo "index is $index"; return   
    fi
  done
}

printf -v var ...읽기 가능한 상태를 유지하려면 (bash-3.1+) 을 사용하세요 eval. 인덱스는 배열로 확장됩니다. 이는 꼭 필요한 것은 아니며 단순 목록도 가능합니다.

또한보십시오배쉬FAQ/006.

답변2

Bash의 배열은 0부터 시작합니다. 그들은 단지 그렇습니다. 즉, 만약 당신이알다 배열이 항상 1부터 시작하는 숫자로 인덱싱되도록 하려면 결과에 +1을 추가하면 됩니다. 함수에 두 번째 인수를 추가하면 시작하거나 결과에 추가할 숫자를 알려주고 두 번째 인수가 누락된 경우에 적합한 기본값을 추가합니다. 또는 다음과 같이 인덱스를 반복합니다.미스터 스퓨라틱제안.

관련 정보