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-
argv1
nullglob
failglob
답변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 셸에 이식 가능하다는 점은 주목할 가치가 있습니다 .