다음을 사용하여 스위치를 구현하는 스크립트가 있습니다.선택 항목 가져오기. 그러나 다음 매개변수를 참조할 수 없습니다.
내 스크립트는 로컬 개발 환경에서 웹 사이트의 백업을 백포트하는 데 사용됩니다. -p
일부 배포 후 단계를 실행하기 위한 스위치를 추가했습니다 . 이것은 내 구문입니다.
backport -p /path/to/website_backup.sql.gz
그래서 전환하기 전에 파일이 지정되었는지, 파일이 올바른지 테스트하고 있습니다. 파일명 경로가 유일한 매개변수이므로 꼭 필요하다고 가정할 수 있으며 첫 번째 매개변수( $1
)가 될 것입니다.
if [[ $# -eq 0 ]] ; then
echo 'Specifcy the sql file to backport.';
exit 0;
fi
if [[ ! -f "$1" ]]; then
echo "$1 is not a valid file.";
exit 0;
fi
내가 찾은이 답변getopts를 사용하여 스위치 매개변수를 구문 분석하는 방법의 예를 보여줍니다.
while getopts "p" opt; do
case $opt in
p) p_post_deploy=true ;; # Handle -a
esac
done
물론, $1
getopts를 구현한 후에는 as 매개변수를 사용하면 작동하지 않습니다. 스위치가 없어도 괜찮습니다. 그러나 첫 번째 매개변수인 스위치를 추가하면 스크립트가 파일인지 테스트합니다.
$ backport -p /path/to/website_backup.sql.gz
-p is not a valid file.
따라서 스위치가 도입되면서 명령의 특정 위치에 나타나는 매개변수에 의존할 수 없게 되었습니다. $2
스위치가 없으면 파일 이름 인수가 두 번째 인수가 될 수 없기 때문에 하드 코딩이 작동하지 않습니다. 저는 스위치 후에 매개변수를 허용하고, 새 스위치 자체를 처리하기 위해 코드만 업데이트하면서 나중에 새 스위치를 도입할 수 있게 해주는 솔루션을 원합니다. 나중에 이동할 수 있음) 새로운 스위치 도입).
getopts를 사용하여 스위치를 구문 분석하는 방법을 알려주는 unix.stackexchange 질문에 대한 답변을 살펴보았습니다.답변 중 하나$*
나머지 매개변수를 나타내는 변수로 언급됩니다.
if [[ "$*" -eq 0 ]] ; then
echo 'Specifcy the sql file to backport.';
exit 0;
fi
그런데 사용하려고 하면 구문을 정확하게 표현하지 못하고 파싱 오류가 발생합니다.
~/scripts/backport: line 14: [[: /d/Downloads/database.sql.gz: syntax error: operand expected (error token is "/d/Downloads/database.sql.gz")
getops 후에 파일 이름 매개변수를 테스트하는 방법은 무엇입니까?
현재 스크립트 버전은 다음과 같습니다.
$ cat backport
#!/bin/bash
set -e
while getopts "p" opt; do
case $opt in
p) p_post_deploy=true ;;
esac
done
shift $(($OPTIND - 1))
# testing what this variable looks like
printf "Remaining arguments are: %s\n" "$*"
if [[ "$*" -eq 0 ]] ; then
echo 'Specifcy the sql file to backport.';
exit 0;
fi
if [[ ! -f "$*" ]]; then
echo "$* is not a valid file.";
exit 0;
fi
drush @local.dev sql-drop -y ;
zcat $1 | drush @local.dev sqlc ;
drush @local.dev cr;
if [ ! -z "$p_post_deploy" ] ; then
echo "Running post-deploy..."
SCRIPT_PATH=$(dirname "$BASH_SOURCE")
source "$SCRIPT_PATH/post-deploy"
post_deploy
fi
답변1
의사소통이 원활하지 못해서 제 탓만 할 수 밖에 없는데, 쿠살라난다가 제가 찾던 답을 댓글로 주셨네요.
getopts
파싱 스위치를 사용한 후
while getopts "p" opt; do
case $opt in
p) p_post_deploy=true ;;
esac
done
이 줄
shift "$((OPTIND - 1))"
모든 스위치는 매개변수 목록에서 제거되므로 스위치가 없는 것처럼 위치 매개변수를 다시 사용할 수 있습니다.
쉘은 OPTIND
자동으로 재설정되지 않습니다. 수동으로 재설정해야 합니다.
답변2
테스트 구조의 적용
if [[ "$*" -eq 0 ]]
부정확하다. -eq
에 사용됩니다정수그리고 $*
인수 목록이 해당 숫자가 아닌 나머지 모든 인수를 참조한다는 점을 감안할 때, 나머지 인수 목록에 단 하나의 요소만 포함되지 않는 한 테스트 구성은 구문 오류를 생성할 수밖에 없습니다. 정수를 나타냅니다(이것은 달성하려는 것이 아닙니다).
이제 실제 작업에서는 "비옵션 매개변수"(예:아니요-<some letter>
임의의 순서를 허용하는 한(즉, 파일 이름이 마지막에 와야 한다고 지정하지 않는 한) 옵션 인수와 함께 "알림"이 앞에 옵니다. 를 사용하려면 getopts
파일 이름을 옵션 인수로 지정하기를 원할 수도 있습니다 -f <filename>
. 그런 다음 사용할 수 있습니다
while getopts "pf:" opt; do
case $opt in
p)
p_post_deploy=true
;;
f)
backportfile=$OPTARG
;;
esac
done
getopts
파일 이름이 지정되지 않으면 자동으로 오류가 발생합니다.
./test.sh: option requires an argument -- f
그런 다음 나중에 다음과 같이 파일이 존재하는지 테스트할 수 있습니다.
if [[ ! -f "$backportfile" ]]
then
echo "$backportfile is not a valid file"
exit 1
fi