bash >5를 사용하여 변수에 지정된 아키텍처를 기반으로 변수에 다른 값을 할당해 보았습니다. 이 작업을 수행하기 위해 함수를 사용합니다. 이것은 완벽하게 작동합니다.
# arguments:
variable name to assign,
value for mac arch,
value for pi arch
create_variable_for_arch() {
if [ "$_run_for_arch" = "mac" ]; then
eval $1=\$2
else
eval $1=\$3
fi
}
그러나 어떤 이유로 인해 내 스크립트가 중단되었습니다.
create_variable_for_arch() {
if [ "$_run_for_arch" = "mac" ]; then
declare "$1"="$2"
else
declare "$1"="$3"
fi
}
다음은 create_variable_from_arch() 사용 방법을 보여주는 스니펫입니다.
declare _moonlight_opt_audio
declare _arch_specific_stream_command
#
while getopts "b:fahdr:s" options; do
case $options in
a)
create_variable_for_arch "_moonlight_opt_audio" \
"--audio-on-host" "-localaudio"
;;
esac
done
create_variable_for_arch "_moonlight_opt_fps" "--fps 60" "-fps 60"
start_streaming() {
_arch_specific_options="$_moonlight_opt_resolution $_moonlight_opt_fps $_moonlight_opt_audio $_moonlight_opt_display_type $_moonlight_opt_bitrate"
create_variable_for_arch "_arch_specific_stream_command" "$_arch_specific_options stream $_target_computer_ip $_moonlight_opt_app_name" "stream $_arch_specific_options -app $_moonlight_opt_app_name $_target_computer_ip"
moonlight $_arch_specific_stream_command
}
eval()을 사용할 때의 추적은 다음과 같습니다.
+ start_streaming
+ _arch_specific_options='--resolution 1920x1080 --fps 60 --bitrate 5000'
+ create_variable_for_arch _arch_specific_stream_command '--resolution 1920x1080 --fps 60 --bitrate 5000 stream 192.168.1.30 StreamMouse' 'stream --resolution 1920x1080 --fps 60 --bitrate 5000 -app StreamMouse 192.168.1.30'
+ '[' mac = mac ']'
+ eval '_arch_specific_stream_command=$2'
++ _arch_specific_stream_command='--resolution 1920x1080 --fps 60 --bitrate 5000 stream 192.168.1.30 StreamMouse'
+ moonlight --resolution 1920x1080 --fps 60 --bitrate 5000 stream 192.168.1.30 StreamMouse
moonlight --resolution 1920x1080 --fps 60 --bitrate 5000 stream 192.168.1.30 StreamMouse
그러나 선언에 따르면 다음과 같습니다.
+ start_streaming
+ _arch_specific_options=
+ create_variable_for_arch _arch_specific_stream_command ' stream 192.168.1.30 ' 'stream -app 192.168.1.30'
+ '[' mac = mac ']'
+ declare '_arch_specific_stream_command= stream 192.168.1.30 '
+ echo moonlight
moonlight
$_arch_특이적_options는 궁극적으로 가치가 없습니다. 무슨 일이야? 변수를 인용하거나 인용하지 않는 몇 가지 다른 방법을 시도했지만 인용이 무엇을 의미하는지 실제로 이해하지 못합니다.
답변1
declare
( typeset
다른 셸과 유사하며 bash
의 별칭 으로도 알려져 있음 declare
)은 현재 범위에서 변수를 선언합니다(유형 및/또는 값을 설정할 수 있음).
따라서 여기서는 함수의 지역 변수를 선언합니다 create_variable_for_arch
. 함수가 반환되면 변수가 사라집니다.
bash
의 declare
/에는 변수를 선언하는 옵션이 typeset
있습니다.-g
글로벌), 그러나 함수 호출자의 범위가 아닌 가장 바깥쪽 범위에서 변수를 선언하고 해당 유형 및/또는 값을 설정하기 때문에 사용할 수 없으므로 거기에서는 꽤 쓸모가 없습니다 .mksh
건너뛰기만zsh
yash
현지화해또는 정적 범위와 함께 ksh93을 사용하십시오.`declare name`과 `declare -g`는 무엇을 합니까?더 알아보기).
따라서 여기서는 eval
nameref를 사용하거나 사용하는 옵션이 있습니다.
create_variable_for_arch() {
if [ "$_run_for_arch" = mac ]; then
eval "$1=\$2"
else
eval "$1=\$3"
fi
}
또는 $_run_for_arch
스크립트에서 상수를 가정합니다.
if [ "$_run_for_arch" = "mac" ]; then
create_variable_for_arch() { eval "$1=\$2"; }
else
create_variable_for_arch() { eval "$1=\$3"; }
fi
또는 nameref를 사용하십시오.
create_variable_for_arch() {
typeset -n _var_name="$1"
if [ "$_run_for_arch" = mac ]; then
_var_name=$2
else
_var_name=$3
fi
}
eval
일반적으로 보안상의 이유로 이를 피하는 것이 (올바로) 권장되지만 eval
올바르게 사용하면 안전합니다. 둘 다 코드를 평가할 수 있으므로 잘못 사용하면 안전 declare
하지 않습니다.namerefs
모두:
f() { eval "$1=\$2"; }
f() { declare "$1=$2"; }
f() { declare -n v="$1"; v=$2; }
reboot
이 명령은 다음과 같이 호출되면 실행됩니다.
f 'a[$(reboot)]' value
임의의 명령 실행 취약점을 방지하려면 첫 번째 인수가 변수 이름인지 확인하는 것이 중요합니다.
f() { declare $1=$2; }
상황은 더욱 악화될 것입니다. 이러한 매개변수 확장은 인용되지 않았기 때문에 분할+글로브의 적용을 받습니다. 따라서 내용조차도 $2
다음과 같이 쉘 코드로 평가될 수 있습니다.
f var 'foo a[$(reboot)]='