Как и в , решение Bruno Bronosky опубликовано , здесь это одно без использования getopt(s)
.
Основная отличительная особенность моего решения заключается в том, что он позволяет объединять параметры, как tar -xzf foo.tar.gz
, равно tar -x -z -f foo.tar.gz
. И так же, как в tar
, ps
и т. Д. Ведущий дефис является необязательным для блока коротких опций (но это можно легко изменить).
#!/bin/sh
echo
echo "POSIX-compliant getopt(s)-free old-style-supporting option parser from phk@[se.unix]"
echo
print_usage() {
echo "Usage:
$0 {a|b|c} [ARG...]
Options:
--aaa-0-args
-a
Option without arguments.
--bbb-1-args ARG
-b ARG
Option with one argument.
--ccc-2-args ARG1 ARG2
-c ARG1 ARG2
Option with two arguments.
" >&2
}
if [ $# -le 0 ]; then
print_usage
exit 1
fi
opt=
while :; do
if [ $# -le 0 ]; then
# no parameters remaining -> end option parsing
break
elif [ ! "$opt" ]; then
# we are at the beginning of a fresh block
# remove optional leading hyphen and strip trailing whitespaces
opt=$(echo "$1" | sed 's/^-\?\([a-zA-Z0-9\?-]*\)/\1/')
fi
# get the first character -> check whether long option
first_chr=$(echo "$opt" | awk '{print substr($1, 1, 1)}')
[ "$first_chr" = - ] && long_option=T || long_option=F
# note to write the options here with a leading hyphen less
# also do not forget to end short options with a star
case $opt in
-)
# end of options
shift
break
;;
a*|-aaa-0-args)
echo "Option AAA activated!"
;;
b*|-bbb-1-args)
if [ "$2" ]; then
echo "Option BBB with argument '$2' activated!"
shift
else
echo "BBB parameters incomplete!" >&2
print_usage
exit 1
fi
;;
c*|-ccc-2-args)
if [ "$2" ] && [ "$3" ]; then
echo "Option CCC with arguments '$2' and '$3' activated!"
shift 2
else
echo "CCC parameters incomplete!" >&2
print_usage
exit 1
fi
;;
h*|\?*|-help)
print_usage
exit 0
;;
*)
if [ "$long_option" = T ]; then
opt=$(echo "$opt" | awk '{print substr($1, 2)}')
else
opt=$first_chr
fi
printf 'Error: Unknown option: "%s"\n' "$opt" >&2
print_usage
exit 1
;;
esac
if [ "$long_option" = T ]; then
# if we had a long option then we are going to get a new block next
shift
opt=
else
# if we had a short option then just move to the next character
opt=$(echo "$opt" | awk '{print substr($1, 2)}')
# if block is now empty then shift to the next one
[ "$opt" ] || shift
fi
done
echo "Doing something..."
exit 0
Для примера использования см. Раздел «Дополнительные параметры». примеры ниже.
Для чего его ценность там опционы с аргументами не являются последними (должны быть только длинные варианты). Таким образом, пока, например, в tar
(по крайней мере, в некоторых реализациях) параметры f
должны быть последними, потому что имя файла следует (tar xzf bar.tar.gz
работает, но tar xfz bar.tar.gz
не делает) это не так (см. более поздние примеры).
В качестве еще одного бонуса параметры параметра потребляются в порядке параметров по параметрам с требуемыми параметрами. Просто посмотрите на вывод моего скрипта здесь с помощью командной строки abc X Y Z
(или -abc X Y Z
):
Option AAA activated!
Option BBB with argument 'X' activated!
Option CCC with arguments 'Y' and 'Z' activated!
Также вы также можете длинные опции в блоке опций, учитывая, что они встречаются последними в блоке. Таким образом, следующие командные строки эквивалентны (включая порядок, в котором обрабатываются параметры и его аргументы):
-cba Z Y X
cba Z Y X
-cb-aaa-0-args Z Y X
-c-bbb-1-args Z Y X -a
--ccc-2-args Z Y -ba X
c Z Y b X a
-c Z Y -b X -a
--ccc-2-args Z Y --bbb-1-args X --aaa-0-args
Все это приводит к:
Option CCC with arguments 'Z' and 'Y' activated!
Option BBB with argument 'X' activated!
Option AAA activated!
Doing something...
Параметры с дополнительными аргументами должны быть возможны с небольшим количеством работы, например глядя вперед, есть ли блок без дефиса; пользователь должен будет поместить дефис перед каждым блоком после блока с параметром, имеющим необязательный параметр. Возможно, это слишком сложно для общения с пользователем, поэтому лучше всего в этом случае просто взять ведущий дефис.
Все становится еще сложнее с несколькими возможными параметрами. Я бы посоветовал не делать параметры, пытаясь быть умными, определяя, может ли для него аргумент или нет (например, с опцией просто принимает число как необязательный аргумент), потому что это может сломаться в будущем.
Я предпочитаю дополнительные опции вместо необязательных аргументов.
Как и с необязательными аргументами, я не поклонник этого (BTW, есть ли там нить для обсуждения плюсов и минусов разных стилей параметров?), но если вы этого хотите, вы могли бы реализовать его сами, как это сделано в http://mywiki.wooledge.org/BashFAQ/035#Manual_loop с оператором case --long-with-arg=?*
, а затем снятие знака равенства (это BTW сайт, в котором говорится, что создание конкатенации параметров возможно с некоторыми усилиями, но «оставило [это] как упражнение для читателя», что заставило меня взять их на их слово, но я начал с нуля).
POSIX-совместимый, работает даже на ancie nt Настройка Busybox, с которой мне приходилось иметь дело (например, cut
, head
и getopts
отсутствуют.
Я нашел, где происходит ошибка, слава Богу! После долгого дня анализа кода я обнаружил свою ошибку, которая связана с запросом на разрешение и работает следующим образом:
- Начиная с Android 6.0, приложения должны запрашивать разрешение на использование некоторых функций из устройство (я сделал эту структуру). Но происходит то, что ниже 6.0 не нужно запрашивать разрешение, и тогда у меня возник конфликт.
Итак, я создал условную структуру для проверки версии Android устройства и, в зависимости от его версии, будет запрашивать разрешения или нет.
Похоже, что вы делаете что-то в собственном коде своего приложения, которое не поддерживается в Android 5. Из комментариев вы можете воспроизвести это в эмуляторе. Так что следующий шаг, чтобы выяснить, что ломает, - это посмотреть на ваш нативный код или даже использовать отладку нативного кода в эмуляторе, чтобы выяснить, в чем его ошибка.
Здесь приведены некоторые документы по отладке собственного кода в Androud Studio .