![bash 함수에 전달하지 않고 $@를 인용하는 방법은 무엇입니까?](https://linux55.com/image/226678/bash%20%ED%95%A8%EC%88%98%EC%97%90%20%EC%A0%84%EB%8B%AC%ED%95%98%EC%A7%80%20%EC%95%8A%EA%B3%A0%20%24%40%EB%A5%BC%20%EC%9D%B8%EC%9A%A9%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
$@
제가 하고 있는 것처럼 전달하지 않고 다른 함수나 다른 스크립트 파일에서 참조하는 방법을 알고 싶습니다 getopts
. 매우 감사합니다!
# 이전 질문: bash getopts는 어떤 매개변수가 호출되는지 어떻게 알 수 있나요?
A() {
B
}
B() {
# how to reference the $@ of A here ?
# which will be 1 2 3 4
}
A 1 2 3 4
답변1
어떤 방식으로든 위치 매개변수를 제공하지 않으면 A
이를 수행할 수 없습니다 . B
다음을 통해 전달할 수 있습니다.
A() {
B "$@"
}
B() {
[ "$#" -eq 0 ] || printf '<%s>\n' "$@"
}
또는 배열에 저장합니다.
A() {
A_args=( "$@" )
B
}
B() {
[ "${#A_args[@]}" -eq 0 ] || printf '<%s>\n' "${A_args[@]}"
}
Bash는 ash/ksh88/zsh(ksh93 또는 zsh의 변수는 아님)와 같은 private
로컬 변수의 범위를 동적으로 지정하므로 A_args
해당 변수 local
를 로 설정할 수도 A
있으며 호출된 function 에서 계속 사용할 수 있습니다 A
.
bash
당신에게 액세스 권한을 부여변하기 쉬운상위 범위인 경우에도그림자 아래unset
지역 변수는 내장 함수(어떤 경우에는 설정 해제되지 않고 대신 상위 범위의 변수를 표시함)로 현재 버그를 이용하여 현재 범위에서 사용되지만 이런 방식으로 상위 범위에서 가져올 수는 없습니다. // 와 반대로 bash에서는 위치 매개변수를 배열 변수에 매핑할 수 없습니다. 왜냐하면 bash 배열 디자인은 배열 이 실제로 배열이 아닌 zsh
Korn 쉘을 기반으로 하기 때문입니다 .rc
fish
일부 코드가 함수의 위치 매개변수나 로컬 옵션을 통해 또는 shift
함수 내에서 액세스하거나 수정할 수 있도록 하려면 해당 코드가 해당 함수의 범위 내에서 실행되어야 합니다. 별도의 기능.set
return
별칭을 사용할 수도 있고 사용하지 않을 수도 있습니다(C 전처리기 매크로에 해당하는 쉘이지만 인수를 허용할 수 없음) eval
.
하지만 참고하세요:
- Bash 쉘에서는 POSIX 모드가 아닌 경우 별칭 확장이 기본적으로 비활성화되어 있으므로
shopt -s expand_aliases
. - 별칭이 존재해야 합니다.앞으로함수의 코드를 읽고 함수 코드 내에서 확장합니다.
그래서 당신은 이것을 할 수 있습니다 :
[ -z "$BASH_VERSION" ] || shopt -s expand_aliases # work around for bash
alias B='{
[ "$#" -eq 0 || printf "<%s>\n" "$@"
shift
}'
A() {
echo "$#"
B
echo "$#"
}
A a b c
또는:
B='
[ "$#" -eq 0 || printf "<%s>\n" "$@"
shift
'
A() {
echo "$#"
eval "$B"
echo "$#"
}
A a b c
답변2
실제로 bash에서 extdebug
이 옵션이 활성화되면(일반적으로 디버거의 경우) 호출 스택의 모든 함수에 대한 위치 인수 목록을 각 수준의 $BASH_ARGV
인수 수(비록 역순이긴 하지만)가 포함된 특수 배열에서 사용할 수 있습니다.$BASH_ARGC
하지만 참고하세요:
- 이는 읽기 전용입니다(값을 변경하려고 해도 아무런 효과가 없습니다).
- extdebug는 처음부터(첫 번째 함수가 호출되기 전) 설정해야 하지만
디버거를 호출하므로 bash 명령줄()에서는 설정할 수 없습니다.bash -O extdebug
- 이 옵션을 활성화하면 추가 효과를 보려면 설명서를 확인하세요.
shopt -s extdebug
shopt -u xpg_echo
A() {
B x y
}
reverse_helper() { caller_args=( "${BASH_ARGV[@]:0:BASH_ARGC}" ); }
B() {
local -a caller_args
local IFS=,
reverse_helper "${BASH_ARGV[@]:BASH_ARGC[0]:BASH_ARGC[1]}"
echo "my args: $*"
echo "my caller args: ${caller_args[*]}"
}
A a b c
이것은 만든다:
my args: x,y
my caller args: a,b,c
답변3
의견을 바탕으로 OP는 함수에서 및 와 같은 내장 함수의 동작을 모방하는 방법을 물었습니다 shift
. getopts
실제로 몇 가지 트릭을 사용하면 이를 달성할 수 있지만 프로덕션에서 사용하는 것이 좋은 생각인지는 확실하지 않습니다.
A() {
B
}
B() {
trap 'shift;trap debug' debug
}
A 1 2 3 4
trap
함수 B의 마지막 명령이어야 합니다.
반환 후 원래 디버그 트랩을 유지하려면 다음을 수행하십시오.
A() {
B
}
B() {
local olddebug="$(trap -p debug)"
trap "shift;trap debug;$olddebug" debug
}
A 1 2 3 4
별칭과 달리 함수는 정의되기 전에 다른 함수에서 참조될 수 있고, 재귀적으로 호출될 수 있으며, 재정의되어 동일한 함수에서 새 버전으로 호출될 수 있습니다. 별칭을 포함하여 스크립트 파일의 모든 항목을 하나의 큰 함수로 래핑하고 해당 함수를 호출하면 별칭이 실패하지만 프로덕션에서도 거의 사용되지 않습니다.