저는 Bash 쉘 스크립팅을 처음 접했고 다음 코드를 작성했습니다. 다른 방법으로는 작동할 수 없지만 이 코드는 매우 엉성한 코드인 것 같습니다.
누군가 이 코드를 관용적(안전하고 간결하며 읽기 쉬운) Bash로 다시 작성하도록 도와줄 수 있습니까? 특히 함수에서 값을 반환하는 더 좋은 방법이 있는지, if 문에서 이를 올바르게 테스트하고 있는지 궁금합니다. (if 문에 괄호를 사용해야 합니까?)
#!/bin/bash
input() {
read -p $'\e[31m\e[1m'"$1"$' [Y/n] \e[0m' -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
return 0
fi
return 1
}
if input "Upgrade Arch?"
then
sudo pacman -Syu
fi
답변1
간단히 명령문에서 함수를 종료하면 함수의 반환 코드가 명령문 자체의 반환 코드가 됩니다.
수표가 [[ $REPLY =~ ^[Yy]$ ]]
좋아 보이는데요. bash에 내장된 대괄호 테스트를 사용하고 있으므로 변수 내부에서 토큰화가 발생하지 않으므로 변수를 인용할 필요가 없습니다. 정규식 검사를 사용하는 것은 좋지만 더 간단한 전역 일치도 [[ $REPLY = [Yy] ]]
작동합니다.
제가 할 주요 변경 사항은 함수 내에서 로컬 변수를 사용하여 이를 에 전달하는 것입니다 read
. 이를 at local
또는 use 로 표시 declare
하면 함수 내에서 변수가 로컬로 사용될 수 있습니다.
errexit
마지막으로, 옵션 ( -e
), nounset
( ) 및 스크립트를 활성화하여 -u
보다 안전하게 만드는 것이 좋습니다. pipefail
이렇게 하면 명령이 실패한 후 스크립트가 계속되는 것을 방지하고 변수 이름의 오타를 찾는 데 도움이 됩니다. 이러한 경우에는 좀 더 방어적으로 코딩해야 하지만(대부분의 명령에서 버그를 명시적으로 테스트하고, 설정되지 않을 수 있는 환경 변수에 기본값을 사용), 예상치 못한 중단이 발생할 때 디버깅이 더 쉬워집니다.
함께 넣어보세요:
#!/bin/bash
set -eu -o pipefail
input() {
declare confirm
declare -r prompt=${1:-"Confirm?"}
read -p $'\e[31m\e[1m'"${prompt}"$' [Y/n] \e[0m' -n 1 -r confirm
echo
[[ $confirm =~ ^[Yy]$ ]]
}
if input "Upgrade Arch?" ; then
sudo pacman -Syu
fi
그리고@StéphaneChazelas제안하면 더 개선할 수도 있습니다.
set -eu -o pipefail
input() {
declare confirm
declare -r prompt=${1:-"Confirm?"}
IFS= read -p $'\e[31;1m'"${prompt}"$' [Y/n] \e[m' -n 1 -r confirm
echo >&2
[[ $confirm = [Yy] ]]
}
if input "Upgrade Arch?" ; then
sudo pacman -Syu
fi