이 쉘 스크립트를 어떻게 단축할 수 있습니까?
CODE="A"
if test "$CODE" = "A"
then
PN="com.tencent.ig"
elif test "$CODE" = "a"
then
PN="com.tencent.ig"
elif test "$CODE" = "B"
then
PN="com.vng.pubgmobile"
elif test "$CODE" = "b"
then
PN="com.vng.pubgmobile"
elif test "$CODE" = "C"
then
PN="com.pubg.krmobile"
elif test "$CODE" = "c"
then
PN="com.pubg.krmobile"
elif test "$CODE" = "D"
then
PN="com.rekoo.pubgm"
elif test "$CODE" = "d"
then
PN="com.rekoo.pubgm"
else
echo -e "\a\t ERROR!"
echo -e "\a\t CODE KOSONG"
echo -e "\a\t MELAKUKAN EXIT OTOMATIS"
exit
fi
답변1
명령문 사용 case
(이식 가능, 유사한 쉘에서 작동 sh
):
case "$CODE" in
[aA] ) PN="com.tencent.ig" ;;
[bB] ) PN="com.vng.pubgmobile" ;;
[cC] ) PN="com.pubg.krmobile" ;;
[dD] ) PN="com.rekoo.pubgm" ;;
* ) printf '\a\t%s\n' 'ERROR!' 'CODE KOSONG' 'MELAKUKAN EXIT OTOMATIS' >&2
exit 1 ;;
esac
CODE
또한 변수 이름을 모두 대문자(예: )에서 소문자 또는 대소문자 혼합(예: code
또는 Code
) 으로 변경하는 것이 좋습니다 . 특별한 의미를 지닌 대문자 이름이 많이 있으며, 그 중 하나를 실수로 재사용하면 문제가 발생할 수 있습니다.
추가 참고 사항: 표준 규칙은 "표준 출력"이 아닌 "표준 오류"에 오류 메시지를 보내는 것입니다 >&2
. 또한 스크립트(또는 프로그램)가 실패하면 exit 1
호출 컨텍스트에서 무엇이 잘못되었는지 알 수 있도록 0이 아닌 상태()로 종료하는 것이 좋습니다 . 또한 다양한 상태를 사용하여 다양한 문제를 나타낼 수도 있습니다(참조:매뉴얼 curl
페이지좋은 예). (제안을 해주신 Stéphane Chazelas와 Monty Harder에게 감사드립니다.)
운영 체제, 버전, 설정 등 간에 이식성이 더 높으므로 ( 및 )를 printf
사용하지 않는 것이 좋습니다. OS 업데이트에 다른 옵션으로 컴파일된 bash 버전이 포함되어 동작이 변경되었기 때문에 많은 스크립트가 손상되는 상황이 있었습니다.echo -e
echo -n
echo
$CODE
여기서는 실제로 큰따옴표가 필요하지 않습니다. 내의 문자열은 case
안전하게 보존할 수 있는 몇 안 되는 컨텍스트 중 하나입니다. 하지만 특별한 이유가 없는 한 변수 참조를 큰따옴표로 묶는 것을 선호합니다. 어디가 안전하고 어디가 안전하지 않은지 추적하기 어렵기 때문에 습관적으로 큰따옴표로 인용하는 것이 더 안전합니다.
답변2
bash
버전 4.0 이상을 사용한다고 가정하면 ...
CODE=A
declare -A domain
domain=(
[a]=com.tencent.ig
[b]=com.vng.pubgmobile
[c]=com.pubg.krmobile
[d]=com.rekoo.pubgm
)
PN=${domain[${CODE,,}]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}
코드에서 저는 모든 도메인 이름을 포함하는 연관 배열을 정의했습니다. 각 도메인 이름은 단일 문자 소문자 키와 연결되어 있습니다.
변수 $PN
에는 배열의 소문자 값에 해당하는 도메인 이름이 할당되지만 $CODE
(소문자로 변환된 값만 반환됨 ${CODE,,}
) 값이 목록의 유효한 항목에 해당하지 않으면 오류와 함께 스크립트가 종료됩니다.$CODE
$CODE
domain
매개변수 ${variable:?error message}
대체는 (코드의 해당 필드) 값으로 확장되지만 $variable
값이 비어 있고 사용할 수 없는 경우 스크립트는 오류 메시지와 함께 종료됩니다. 코드에서와 정확히 동일한 오류 메시지 형식을 얻지는 못하지만 본질적으로성능$CODE
유효하지 않은 경우에도 동일:
$ bash script.sh
script.sh: line 12: domain[${CODE,,}]: ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS
문자 수에 관심이 있는 경우 문자 수를 더 줄일 수 있습니다.
CODE=A
declare -A domain=( [a]=tencent.ig [b]=vng.pubgmobile [c]=pubg.krmobile [d]=rekoo.pubgm )
PN=com.${domain[${CODE,,}]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}
불필요한 개행 문자를 제거하는 것 외에도 com.
각 도메인에서도 제거했습니다(대신 배포판에 추가했습니다 PN
).
위의 모든 코드는 다중 문자 값에도 작동합니다 $CODE
(해당 소문자 키가 배열에 있는 경우 domain
).
숫자(0부터 시작) 인덱싱 의 경우 $CODE
코드가 약간 단순화됩니다.
CODE=0
domain=( com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm )
PN=${domain[CODE]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}
domain
또한 한 줄에 하나의 항목이 포함된 보조 파일에서 배열을 읽는 것이 매우 쉽습니다.
CODE=0
readarray -t domain <domains.txt
PN=${domain[CODE]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}
답변3
쉘이 배열을 허용하는 경우 가장 짧은 대답은 bash의 다음 예와 같습니다.
declare -A site
site=( [a]=com.tencent.ig [b]=com.vng.pubgmobile [c]=com.pubg.krmobile [d]=com.rekoo.pubgm )
pn=${site[${code,}]}
이는 $code
a, b, c 또는 d만 가능하다고 가정합니다.
그렇지 않은 경우 다음과 같은 테스트를 추가하십시오.
case ${site,} in
a|b|c|d) pn=${site[${code,}]};;
*) pn="default site"
printf '\a\t %s\n' 'ERROR!' 'CODE KOSONG' 'MELAKUKAN EXIT OTOMATIS'
exit 1
;;
esac
답변4
문자를 사용하여 값의 색인을 생성합니다. 숫자를 사용하면 다음과 같이 간단해집니다.
code=1
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
eval pn\=\${"$code"}
이는 대부분의 쉘에서 작동하는 이식 가능한 쉘 코드입니다.
Bash의 경우 다음을 사용할 수 있습니다. pn=${!code}
또는 bash/ksh/zsh의 경우 다음을 사용할 수 있습니다 pn=${@:code:1}
.
편지
문자(a~z 또는 A~Z)를 사용해야 하는 경우 해당 문자를 인덱스로 변환해야 합니다.
code=a # or A, B, C, ... etc.
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
eval pn\=\"\${$(( ($(printf '%d' "'$code")|32)-96 ))}\"
긴 코드에서 각 부분의 의도와 의미를 명확히 합니다.
code=A
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
asciival=$(( $(printf '%d' "'$code") )) # byte value of the ASCII letter.
upperval=$(( asciival | 32 )) # shift to uppercase.
indexval=$(( upperval - 96 )) # convert to an index from a=1.
eval arg\=\"\$\{$indexval\}\" # the argument at such index.
소문자로 변환해야 하는 경우 다음을 사용하세요( $(( asciival & ~32 ))
ASCII 값의 비트 6이 설정되지 않았는지 확인하세요).
에러 코드
오류가 발생할 때 스크립트가 인쇄하는 출력은 매우 길며 매우 구체적입니다.
이를 처리하는 가장 일반적인 방법은 함수를 정의하는 것입니다.
errorcode(){ exitcode=$1; shift; printf '\a\t %s\n' "$@"; exit "$exitcode"; }
그런 다음 필요한 특정 메시지를 사용하여 함수를 호출하세요.
errorcode 27 "ERROR!" "CODE KOSONG" "MELAKUKAN EXIT OTOMATIS"
최종 종료 값은 exitcode
(여기 예에서는 27)로 제공됩니다.
전체 스크립트(오류 검사 포함)는 다음과 같습니다.
errorcode(){ exitcode=$1; shift; printf '\a\t %s\n' "$@"; exit "$exitcode"; }
code=${1:-A}
case "$code" in
[a-d]|[A-D]) : ;;
*) errorcode 27 "ERROR!" "CODE KOSONG" "MELAKUKAN EXIT OTOMATIS" ;;
esac
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
eval pn\=\"\${$(( ($(printf '%d' "'$code") & ~32) - 64 ))}\"
printf 'Code=%s Argument=%s\n' "$code" "$pn"