Я только что получил ответ от своей хостинговой компании (OVH ). Получается, CIFS и NFS заблокированы за пределами своей сети. Предлагают использовать SSHFS, мы решили проблему с FTP.
Используйте оператор 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
), чтобы любой контекст вызова мог сказать, что пошло не так. Также можно использовать разные статусы для обозначения различных проблем (см. хороший пример в разделе «КОДЫ ВЫХОДА» на странице руководства curl
). (Спасибо Стефану Шазеласу и Монти Хардеру за предложения.)
Я рекомендую printf
вместоecho -e
(и echo -n
), потому что он более переносим между операционными системами, версиями, настройками и т. д. Однажды у меня сломалась куча моих скриптов, потому что обновление ОС включало скомпилированную версию bash. с различными опциями, которые изменили поведение echo
.
Двойные -кавычки вокруг $CODE
здесь на самом деле не нужны. Строка в case
— один из немногих контекстов, где их можно безопасно опустить. Тем не менее, я предпочитаю двойные -кавычки ссылок на переменные, если только нет особой причины не делать этого, потому что трудно отследить, где это безопасно, а где нет, поэтому безопаснее просто двойное -цитирование.
Если ваша оболочка допускает массивы, самый короткий ответ должен быть похож на этот пример в 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
Если вы используете 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
).
Если бы $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}
Вы используете буквы для индексации значений, если бы вы использовали числа, это было бы так же просто, как:
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 ))
(убедитесь, что бит 6 значения ascii не установлен ).
Вывод, который ваш сценарий выводит при ошибке, довольно длинный (и конкретный ).
Самый универсальный способ справиться с этим — определить функцию:
errorcode(){ exitcode=$1; shift; printf '\a\t %s\n' "$@"; exit "$exitcode"; }
А затем вызовите эту функцию с конкретным сообщением (s ), которое вам нужно.
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"
Я собираюсь ответить на этот вопрос в другом направлении. Вместо кодирования данных в сценарии поместите эти данные в отдельный файл данных, а затем используйте код для поиска в файле :
.$ cat names.cfg
a com.tencent.ig
b com.vng.pubgmobile
c com.pubg.krmobile
d com.rekoo.pubgm
$ cat lookup.sh
PN=$(awk -v code="${1:-}" 'tolower($1) == tolower(code) { print $2; }' names.cfg)
if [ -z "${PN}" ]; then
printf '\a\t%s\n' 'ERROR!' 'CODE KOSONG' 'MELAKUKAN EXIT OTOMATIS' >&2
exit 1
fi
echo "${PN}"
$ bash lookup.sh A
com.tencent.ig
$ bash lookup.sh a
com.tencent.ig
$ bash lookup.sh x
ERROR!
CODE KOSONG
MELAKUKAN EXIT OTOMATIS
Разделение этих проблем имеет несколько преимуществ:
look
для эффективного бинарного поиска (, а не по строкам -по -строкам grep
] илиawk
)