쉘 함수의 다른 변수에 $@ 할당

쉘 함수의 다른 변수에 $@ 할당

gcgit 커밋/체크아웃을 구별할 수 있는 스마트 별칭을 만들고 있습니다 .

인수 없이 호출하거나 , 인수를 사용하여 호출하면 gcgit commit이 실행됩니다. 그렇지 않으면 git checkout을 실행하십시오(추가 매개변수가 있는 플래그가 있는 경우). gc의 다른 변형이 호출되면 예상치 못한 작업을 수행하기보다는 오류를 발생시키기를 원합니다.-a-mb

이것은 지금까지 나의 쉘 기능입니다.

gc() {
    args=$@
    commit=false
    checkout=false

    # Check flags
    while getopts ":am:b" opt; do
        case $opt in
            a|m)
                commit=true
                ;;
            b)
                checkout=true
                ;;
            \?)
                echo "Unknown flags passed."
                return 1
                ;;
        esac
    done

    shift "$((OPTIND-1))"

    # Check number of arguments
    if [[ "$#" == 0 ]]; then
        commit=true
    elif [[ "$#" == 1 ]]; then
        checkout=true
    else
        echo "Too many arguments"
        return 1
    fi

    # Finally run respective command
    if [[ $commit == true && $checkout == true ]]; then
        echo "Unable to ascertain which operation you would like to perform."
        return 1
    elif [[ $commit == true ]]; then
        git commit "$args"
    elif [[ $checkout == true ]]; then
        git checkout "$args"
    else
        echo "Undefined behavior"
        return 1
    fi
}

그러나 이것은 제대로 작동하지 않습니다. 몇 가지 실험을 통해 다른 변수에 할당하는 것이 근본 원인이라는 것을 알았지 $@만 왜 그리고 정확히 무엇이 잘못되었는지 이해할 수 없습니다.

또한 쉘 함수를 작성하는 것은 이번이 처음이므로 제가 저지른 실수를 지적해 주시기 바랍니다.

답변1

$@배열인 경우 배열에 할당합니다.

args=("$@")

그런 다음 배열로 사용하십시오.

elif [[ $commit == true ]]; then
    git commit "${args[@]}"
elif [[ $checkout == true ]]; then
    git checkout "${args[@]}"
else

현재 코드에서 일어나는 일은 모든 개별 매개변수가 단일 문자열로 저장된다는 것입니다. 따라서 전화를 하면:

bc -a "foo bar"

다음과 같이 할당됩니다 args.

args='-a foo bar'

그런 다음 실행하는 대신 다음을 수행하십시오.

git commit -a "foo bar"

당신은 다음을 얻습니다:

git commit '-a foo bar'

기타 참고사항:

  • "$args[@]"zsh에서는 or "${(@)args}"대신 사용할 수도 있지만 "${args[@]}"bash/ksh에서는 사용할 수 없습니다. "$args"yash에서 작동하지만 ksh/bash에서는 zsh(연결된 요소의 첫 번째 문자) 및 ksh/bash와 동일합니다. zsh에서는 이것이 작동하지만 빈 요소가 있는 경우 제거됩니다."$args[*]"$IFS"${args[0]}"$args
  • getopts함수에서 사용할 때는 미리 무언가를 추가해야 합니다 local OPTIND OPTARG(특히 OPTIND또는 적어도 초기화/설정 해제). zsh는 OPTIND다른 쉘을 에뮬레이션하지 않을 때 이 작업을 자동으로 수행하지만 ksh/bash/yash는 그렇지 않습니다. 함수 내에서 사용하는 다른 변수도 지역 변수로 설정해야 합니다.
  • 오류는 stderr(fd 2)로 전송되어야 합니다 echo>&2 Too many arguments.

답변2

다른 답변은 POSIX가 아니므로 여기에 대안이 있습니다. 일시적으로 위치 매개변수를 분쇄하려면 다음을 수행하십시오.

s1=$(printf '%s\n' "$@")

그런 다음 복구할 준비가 되면 다음을 수행하세요.

IFS='
'
set -- $s1

이는 인수에 개행 문자가 포함되어 있지 않다고 가정합니다. 이렇게 하면 다른 구분 기호를 사용해야 합니다.

참고 사항: 마지막 줄에는 따옴표가 없는 변수가 포함되어 있습니다. 이는 인용되지 않은 변수가 허용되는 몇 안 되는 경우(제 생각에는 유일한 경우) 중 하나입니다. 사용자가 명시적으로 설정한 경우입니다 IFS. 사용자는 본질적으로 "예, 제가 하고 있는 일을 알고 있습니다. 계속하십시오"라고 말합니다. .

관련 정보