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을 추가하면 됩니다. 함수에 두 번째 인수를 추가하면 함수에 시작하거나 결과에 추가할 숫자를 알려주고 두 번째 인수가 누락된 경우 합리적인 기본값을 추가합니다. 또는 다음과 같이 인덱스를 반복합니다.스프라틱 씨제안.

관련 정보