Термин «язык сценариев» в наши дни действительно является двусмысленным, бессмысленным или просто предвзятым, но обсуждение того, как это произошло, является обсуждением эволюции языков, к которым часто применяется этикетка.
Первоначально сценарии относились к языкам, исходный код которых интерпретировался во время выполнения, а не компилировался (например, оболочки, такие как bash), но он стал применяться к таким языкам, как python и perl, которые (на по крайней мере, в их нынешних воплощениях) предварительно скомпилированы в байт-код , а затем выполнены. Неоднозначность здесь заключается в том, что другие языки, такие как java, работают таким же образом, но никто не называет java «языком сценариев».
Причина, по которой они были объединены с оболочкой (я полагаю, это исходный «язык сценариев»), вероятно, потому, что они были, по крайней мере, на порядок медленнее, чем чисто компилируемые языки, и поэтому до того, как у нас были компьютеры, это различие было сделано несколько несущественным в более широком диапазоне контекстов, они в основном использовались для запуска коротких «скриптов» с одним исходным файлом. То же самое можно сказать и о большинстве динамических веб-материалов до 12-15 лет назад - большинство из них просто использовали короткие сценарии CGI с небольшим количеством (часто встроенного / встроенного) javascript (дополнительная двусмысленность : java * script * обычно исключается из категории "язык сценариев", потому что он не является универсальным).
Таким образом, при обсуждении того, что сегодня в разговорной речи (или предвзято) называется основной серверной частью «языков сценариев», вероятно, имеет смысл использовать термин объектно-ориентированные языки с динамической типизацией (вы могли бы бросить в «общего назначения» или «на стороне сервера», чтобы исключить javascript, который также является объектно-ориентированным и динамически типизированным). К ним относятся:
Perl
Python
PHP
Ruby
Они отличаются от других распространенных серверных технологий, таких как Java и C #, тем, что они используют динамический вместо статическая типизация, и это, опять же, то, почему то, что обычно подразумевается под "языком сценариев" в контексте веб-технологий, на самом деле является динамически типизированным объектно-ориентированным языком (который, безусловно, включает javascript, если мы не учитываем " на стороне сервера »). Ирония здесь в том, что это исключает языки, не относящиеся к объектно-ориентированному программированию, такие как оболочка, но оболочка все равно больше не используется в веб-программировании.
Будет проще, если вы установите отдельные флаги для каждой активированной опции, чтобы вам не приходилось анализировать еще одну строку, чтобы проверить, использовалась ли опция.
Например:
#!/bin/bash
self=$0
show_help () {
cat <<END_HELP
Usage: $self [-r] [-l|-u] pathname [...]
Options:
info about options here
END_HELP
}
recurse=0 # don't recurse by default
lowercase=1 # lowercase by default
while getopts rluh opt; do
case $opt in
r) recurse=1 ;;
l) lowercase=1 ;;
u) lowercase=0 ;;
h) show_help
exit ;;
*) echo 'Error in parsing options' >&2
exit 1
esac
done
shift "$(( OPTIND - 1 ))"
for pathname do
if [ -d "$pathname" ] && [ "$recurse" -eq 1 ]; then
# recurse here
fi
if [ "$lowercase" -eq 1 ]; then
# turn into lowercase
else
# turn into uppercase
fi
done
Обратите внимание, что код после shift
является просто примером кода. Я бы посоветовал вам вместо цикла использовать find
для выполнения рекурсии (, возможно, во всех случаях, даже если флаг recursion
не установлен ).
Между прочим, shift
избавляется от всех проанализированных опций из "$@"
, так что в списке позиционных параметров остаются только операнды пути. Это то, что цикл впоследствии повторяет.
Код, как написано выше, использует разумные значения по умолчанию (они должны быть упомянуты в тексте справки ). Это означает, что вполне нормально запускать скрипт без каких-либо опций. В качестве примечания, запуск инструмента с без аргументов, вероятно, не должен приводить к ошибке. Работы нет, поэтому не надо делать никакой работы.
Что-то вроде FLAGS+=r
добавит r к FLAGS. Следовательно, для modify -r -l
FLAGS будет rl
. Вы должны использовать одну переменную для каждой опции (FLAG_r
).
Сравнение "$2" -eq 0
будет работать только в том случае, если скрипт получит два имени каталога, второе из которых будет 0
. Лучшее сравнение было бы "$2" = ""
.
Вы объединяете буквы флага в одну строку, поэтому с помощью myscript -l -r
вы получаете FLAGS=lr
, что не равно ни l
, ни r
.
Вы можете использовать сопоставление с образцом вместо проверки на равенство, чтобы справиться с этим:
if [[ $FLAGS = *r* ]]; then
echo "flag -r was given"
или добавьте отдельные переменные для каждого флага:
r_flag=
l_flag=
while getopts "rluh" opt; do
case $opt in
r) r_flag=1;;
...
if [[ $r_flag ]]; then
echo "flag -r was given"
В любом случае, вы, скорее всего, захотите shift $(( OPTIND - 1 ))
после цикла while getopts
, чтобы опции, обрабатываемые getopts
, были удалены из позиционных параметров, а то, что осталось в $1
, $2
... аргументы скрипта, указанные после опций.