bash 함수나 스크립트의 마지막 위치 인수를 팝하는 방법은 무엇입니까?

bash 함수나 스크립트의 마지막 위치 인수를 팝하는 방법은 무엇입니까?

bash 함수나 스크립트의 마지막 위치 인수를 표시해야 하는 경우가 종종 있습니다.

"팝"이란 "위치 인수 목록에서 이를 제거하고 (선택적으로) 변수에 할당합니다."를 의미합니다.

이 작업이 얼마나 자주 필요한지 생각해 보면 제가 찾은 최상의 결과가 아래 예에 나와 있다는 사실에 조금 놀랐습니다.

foo () {
    local argv=( "$@" )
    local last=${argv[$(( ${#argv[@]} - 1 ))]}
    argv=( ${argv[@]:0:$(( ${#argv[@]} - 1 ))} )
    echo "last: $last"
    echo "rest: ${argv[@]}"
}

즉, 수천 명의 배우가 참여하는 대서사적 작품...

더 간단하고 읽기 쉬운 것이 있습니까?

답변1

(bash 4.2 이상)을 사용하여 마지막 요소에 액세스하고 ${argv[-1]}내장 함수(bash 4.3 이상)를 사용하여 배열에서 해당 요소를 제거할 수 있습니다.unset

last=${argv[-1]}
unset 'argv[-1]'

전역 연산자 argv[-1]와 마찬가지로 주변 따옴표가 필요하므로 따옴표가 없는 따옴표는 및/또는 파일이 현재 디렉터리에 존재하는 경우 확장될 수 있습니다(또는 파일 이 없거나 활성화되어 있지 않으면 아무것도 하지 않거나 오류가 발생합니다).[...]argv[-1]argv-argv1nullglobfailglob

답변2

이건 어때:

foo () {
    local last="${!#}"
    local argv=("${@:1:$#-1}")
    echo "last: $last"
    echo "rest: ${argv[@]}"
}

답변3

읽기 쉽게 만들기 위해 조금 단순화할 수 있지만 기본 접근 방식은 동일합니다(지원되지 않는 Bash 버전이 있는 경우 유용할 수 있음).콰지모도의 헌신):

foo () {
    local argv=( "$@" )
    local last="${argv[$# - 1]}"
    argv=( "${argv[@]:0:$# - 1}" )
    echo "last: $last"
    echo "rest: ${argv[@]}"
}

이렇게 사용하는 것이 약간 건방진 것은 인정 $#하지만, 다음과 같은 효과가 있습니다.${#argv[@]} 이 구체적인 예에서는그리고 코드가 더 간결해졌습니다.

답변4

더 간단하게 동등한 경우bxm의 답변, 사용 set:

pop() {
  last="${!#}"  # see man bash, search for "indirect expansion"
  set -- "${@:1:$#-1}"

  printf 'not last: %s\n' "$@"
  printf 'last: %s\n' "${last}"
}

pop 1 2 3 4
# prints:
# not last: 1
# not last: 2
# not last: 3
# last: 4

여기서는 ${!#}간접 인수 확장("간접 확장" 검색) man bash이며 set -- ARGS...인수( $1등)의 새 값을 지정된 인수에 설정합니다.

${!#}배열 슬라이싱은 bashism이지만 set --모든 POSIX 셸에 이식 가능하다는 점은 주목할 가치가 있습니다 .

관련 정보