배열을 함수 매개변수로 전달하지만 다른 추가 매개변수를 사용하는 방법은 무엇입니까?

배열을 함수 매개변수로 전달하지만 다른 추가 매개변수를 사용하는 방법은 무엇입니까?

다음 게시물해결책예상대로 작동합니다.

그래서 - 그의 대답으로 판단하면:

function copyFiles() {
   arr=("$@")
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one 1" "two 2" "three 3")

copyFiles "${array[@]}"

이 글을 쓰는 이유는 다음과 같은 경우 어떻게 해야 하는지입니다.

copyFiles "${array[@]}" "Something More"
copyFiles "Something More" "${array[@]}"

질문:전송된 인수와 수신된 인수가 함수에 있다는 것을 알고 있습니다. 실제로는 병합되어 있으므로 $1" $2배열" 매개변수가 더 이상 예상대로 작동하지 않습니다.통합다른 주장으로

나는 연구를 했습니다:

typeset -n슬프게도아니요일하다

그리고:

하다아니요${#array[@]}예상대로 작동합니다. 해당 답변에는 함수 내에서 배열 크기()가 다른 것과 관련하여 데모 테스트/검증 링크와 함께 문제가 있다는 설명이 있습니다 .

그렇다면 이 목표를 달성하는 방법은 무엇입니까?

답변1

이와 같이 배열을 매개변수로 전달할 수 없습니다. 한 것처럼 보이지만 예상한 대로 작동하지 않습니다.

귀하의 쉘(예: 여기 :)은 개별 프로젝트로 bash확장됩니다."${array[@]}"앞으로기능을 실행해보세요!

그래서 이거

copyFiles "Something More" "${array[@]}"

실제로 전화를 걸어

copyFiles "Something More" "one 1" "two 2" "three 3"

따라서 함수 내의 다른 매개변수와 배열을 구별하는 것은 불가능합니다.

(너할 수 있다 배열에 대한 참조 추가, 그러나 이식성이 떨어지는 것처럼 보이고 필요하지 않은 경우 범위를 혼합하고 싶지 않으므로 사용하지 않는 것이 좋습니다.


shift예를 들어 를 사용할 수 있습니다 .

copyFiles() {
    var1=$1
    shift
    for i in "$@"; do ... ; done
}

(이것은 arr=("$@")중복되어 $@이미 배열이므로 지정할 필요도 없으며 "$@"그냥 사용할 수도 있습니다 for i; do ...; done.)

또는 다음과 같은 매개변수를 구문 분석합니다.getopts.

답변2

이 작업을 직접적으로 수행할 수는 없으며 어쨌든 별로 좋지 않습니다. 배열은 실제로 Bash에서 일급 객체가 아니며, 이와 같은 작업을 수행해야 하는 경우 실제 프로그래밍 언어로 전환하는 것을 고려할 수 있습니다...

핵심 문제는 "${array[@]}"실제로 배열 자체를 제공하는 것이 아니라 배열의 모든 요소(목록)로 확장하는 것입니다(인덱싱은 잊어버리세요!).

확실히 몇 가지 해결 방법이 있지만 이것이 매우 좋다고 할 수 있을지 확신할 수 없습니다. 하지만 넌 할수있어...

  1. 몇 가지 구분 기호를 사용하세요.

    func "non-array" "arguments" :: "${array[@]}" 
    

    이것이 본질적으로 GNU Parallel이 하는 일이지만 실제 매개변수로 사용할 수 없는 일부 값을 결정해야 한다는 단점이 있습니다. (또는 그것을 탈출하는 어떤 방법은 아마도 더 나쁠 것입니다.) 구분 기호를 찾으려면 매개변수 목록을 스캔해야 합니다.

  2. 목록의 길이를 알려주는 매개변수를 추가합니다.

    func 1 "non-array argument" "${#array[@]}" "${array[@]}" 
    

    이것은 유효한 값을 전달할 만큼 충분히 일반적이어야 하지만 C에서 수동 메모리 처리에 대한 고통스러운 기억을 불러일으키기 시작하더라도 나는 당신을 비난하지 않을 것입니다. 다른 쪽 끝에서 구문 분석하는 것은 그것을 하고 싶어할 정도로 미친 사람에게는 연습 역할도 합니다.

  3. 대신 이름으로 배열을 전달하십시오.

    예를 들어 다음과 같이 nameref를 사용할 수 있습니다.

    fun() {
        local _arrayname="$1"
        local -n _ref="$1"
        printf "array '%s' has %d members\n" "$_arrayname" "${#_ref[@]}"
        printf "member at index #2 is '%s'\n" "${_ref[2]}"
    }
    asdf=(one too tree)
    fun asdf
    

    간접 구문을 사용해 볼 수도 있지만 ${!p}IIRC, 배열 인덱싱은 해당 구문을 사용하는 것이 더 어렵습니다. 물론 둘 다 이식 불가능하므로 Bash를 사용하게 될 수도 있지만 Bash는 버전 4.4 이상부터 이름 참조를 지원하므로 대부분의 경우 문제가 되지 않습니다.

    namerefs의 문제는 네임스페이스 충돌입니다. 위 함수에 _arraynameor라는 이름의 배열을 전달할 수 없습니다._ref

관련 정보