getopts
여러 번 사용할 수 있도록 일부 논리를 함수로 이동하여 사용자에게 지정된 매개변수의 순서에 더 많은 유연성을 제공하려고 합니다 .
print-usage() {
echo "myssh [options] <host> [options] [-- ssh-options...]" >&2
exit 1
}
extra_args=()
parse-args() {
while getopts ":hvV:" opt; do
case ${opt} in
(h) print-usage ;;
(v) extra_args+=('-L 5900:localhost:5900') ;;
(V) extra_args+=("-L $OPTARG:localhost:5900") ;;
(\?) echo "Invalid option: -$OPTARG" >&2 ;;
(:) echo "Invalid option: -$OPTARG requires an argument" >&2 ;;
esac
done
echo $((OPTIND -1))
}
shift $(parse-args $@)
host=$1
shift
shift $(parse-args $@)
ssh $host $extra_args $@
내 문제는 이것이 parse-args() { ... extra_args+=(...) }
전역 변수에 영향을 미치지 않는다는 것입니다 extra_args
. 나는 하위 쉘이 상위 범위 변수에 쓸 수 없으며 일반적으로 stdout을 사용해야 한다는 것을 알고 있지만 stdout을 이동된 정수로 사용했습니다.
이 문제는 일반적으로 어떻게 해결됩니까?
답변1
(태그된 대로) 사용하고 있으므로 bash
배열 변수를 사용할 수 있습니다. 당신이 할 수 없는 일은 서브쉘 shift $(parse_args "$@")
에 있는 this 와 같은 호출을 통해 전역 변수에 영향을 미치는 것입니다 . parse_args
다음은 함수 외부에 값 배열을 전달하는 대체 솔루션입니다.
#!/bin/bash
#
extra_args1=()
extra_args2=()
usage() {
echo "myssh [options] <host> [options] [-- ssh-options...]" >&2
exit 1
}
parse_args() {
local OPT OPTIND=1 OPTARG args=()
while getopts ":hvV:" OPT
do
case "$OPT" in
(h) usage ;;
(v) args+=('-L' '5900:localhost:5900') ;;
(V) args+=('-L' "$OPTARG:localhost:5900") ;;
(\?) echo "Invalid option: -$OPTARG" >&2 ;;
(:) echo "Invalid option: -$OPTARG requires an argument" >&2 ;;
esac
done
echo $((OPTIND -1)) "${args[@]}"
}
# Get number to shift plus set of arguments
extra_args1=($(parse_args "$@"))
shift ${extra_args1[0]}
unset extra_args1[0]
# Position dependent value
host="$1"
shift
# Get number to shift plus set of arguments
extra_args2=($(parse_args "$@"))
unset extra_args2[0]
# "${x[@]}" values are interpolated as quoted and vanish if fully empty
ssh "$host" "${extra_args1[@]}" "${extra_args2[@]}" "$@"
큰따옴표를 사용하면 "$@"
개별 값 자체가 큰따옴표로 처리될 뿐만 아니라 확장할 값이 없으면 전체 확장이 사라지는 마법을 사용할 수 있습니다. 동일한 기능을 사용하여 "${extra_args1[@]}"
확장을 처리할 수 있습니다."${extra_args2[@]}"
이 방법의 한 가지 잠재적인 단점은 그 a=($(function))
자체가 와일드카드의 적용을 받기 때문에 function
와일드카드가 반환되면 배열 할당의 일부로 확장된다는 것입니다 a
. 이 문제에 대한 좋은 해결책이 없습니다.
답변2
파이프를 사용하여 가능한 솔루션입니다 FIFO
. 함수에서 정의하는 대신 extra_args
함수를 사용하여 파이프에 쓰고 extra_args
함수를 호출한 후 읽습니다.
#!/bin/bash
trap "rm -rf extraargpipe" ERR EXIT
mkfifo extraargpipe
parseargs() {
echo 1 > extraargpipe &
echo 2 > extraargpipe &
}
parseargs
extra_args=$(cat extraargpipe)
echo ${extra_args}
FIFO 논리(또는 올바르게 기억한다면 실제로 경쟁 조건)로 인해 반환되지만 2 1
잘못된 순서는 ssh
정의한 옵션에 문제가 되지 않습니다. 비슷한 것을 만들고 싶다면 -o opt1,opt2,opt3
그게 전부입니다.
임시 파일을 사용하여 거의 동일한 작업을 수행할 수 있습니다.