Как мне проанализировать необязательные аргументы в сценарии bash, если порядок не указан?

Согласно документации к dnf clean:

Выполняет очистку временных файлов, хранящихся для репозиториев. Сюда входят любые данные, оставшиеся после отключенных или удаленных репозиториев, а также для различных версий выпуска дистрибутива.

dnf clean dbcache (очистить dbcache)

Удаляет файлы кэша, созданные на основе метаданных репозитория. Это заставляет DNF заново создавать файлы кэша при следующем запуске.

dnf clean expire-cache (очистить кэш)

Помечает метаданные хранилища просроченными. При следующем использовании DNF заново проверит кэш для каждого репозитория.

dnf clean metadata (очистить метаданные)

Удаляет метаданные репозитория. Это файлы, которые DNF использует для определения удаленной доступности пакетов. Использование этой опции заставит DNF загрузить все метаданные при следующем запуске.

dnf clean packages

Удаляет все кэшированные пакеты из системы.

dnf clean all

Выполняет все вышеперечисленные действия.

Итак, если dnf clean all не очистил его, значит, он не является частью кэша dnf. Кэш dnf живет в /var/cache/dnf; /var/cache/yum может быть остатком предыдущей версии Fedora (до обновления с yum на dnf), и вы почти наверняка можете безопасно удалить файлы в этом каталоге.

13
20.12.2016, 00:46
4 ответа

В этой статье показаны два разных способа - shift и getopts (и обсуждаются преимущества и недостатки из двух подходов).

С помощью shift ваш сценарий просматривает $ 1 , решает, какое действие предпринять, а затем выполняет shift , перемещая $ 2 в $ 1 , $ 3 до $ 2 и т. Д.

Например:

while :; do
    case $1 in
        -a|--flag1) flag1="SET"            
        ;;
        -b|--flag2) flag2="SET"            
        ;;
        -c|--optflag1) optflag1="SET"            
        ;;
        -d|--optflag2) optflag2="SET"            
        ;;
        -e|--optflag3) optflag3="SET"            
        ;;
        *) break
    esac
    shift
done

С помощью getopts вы определяете (короткие) параметры в выражение while :

while getopts abcde opt; do
    case $opt in
        a) flag1="SET"
        ;;
        b) flag2="SET"
        ;;
        c) optflag1="SET"
        ;;
        d) optflag2="SET"
        ;;
        e) optflag3="SET"
        ;;
    esac
done

Очевидно, это всего лишь фрагменты кода, и я не учел валидацию - проверку того, что обязательные аргументы flag1 и flag2 установлены, и т. д.

Какой подход вы используете в некоторой степени дело вкуса - насколько переносимым вы хотите, чтобы ваш сценарий был, можете ли вы жить только с короткими (POSIX) параметрами или хотите ли вы длинные (GNU) параметры и т. д.

38
27.01.2020, 19:52

Если ваши параметры input являются позиционными (вы знаете, в каких местах они находятся) и не указываются с помощью флагов, то вам нужно просто создать командную строку. Просто подготовьте аргументы команды для всех из них:

FLAG1="--flag1 $1"
FLAG2="--flag2 $2"
OPTFLAG1=""
OPTFLAG2=""
OPTFLAG3=""
if [ xFALSE != x"$3" ]; then
   OPTFLAG1="--optflag1 $3"
fi
if [ xFALSE != x"$4" ]; then
   OPTFLAG2="--optflag2 $4"
fi
#the same for other flags

#now just run the program
runprogram $FLAG1 $FLAG2 $OPTFLAG1 $OPTFLAG2 $OPTFLAG3

Если параметры не указаны, то соответствующие строки пусты и превращаются в ничто. Обратите внимание, что в последней строке нет кавычек. Это потому, что вы хотите, чтобы оболочка разделяла параметры на слова (чтобы предоставить - flag1 и $ 1 в качестве отдельных аргументов вашей программе). Конечно, это пойдет не так, если ваши исходные параметры содержат пробелы. Если это вы запускаете, вы можете оставить его, но если это общий сценарий, он может иметь неожиданное поведение, если пользователь вводит что-то с пробелами. Чтобы справиться с этим, вам нужно сделать код немного уродливее.

Префикс x в тесте [] присутствует в случае, если $ 3 или $ 4 пусто. В этом случае bash расширит [FALSE! = $ 3] на [FALSE! =] , что является синтаксической ошибкой, поэтому есть еще один произвольный символ, чтобы защититься от этого. Это очень распространенный способ, вы увидите его во многих скриптах.

Я установил OPTFLAG1 , а остальные - на "" в начале, чтобы быть уверенным (в случае, если они были установлены на что-то раньше), но если они не были фактически объявлен в окружении, то этого делать строго не нужно.

Пара дополнительных замечаний:

  • Фактически вы можете просто получить параметры так же, как это делает runprogram : с флагами. Вот о чем говорит Джон Н. . Вот где пригодится getopts .
  • Использование FALSE для этой цели немного нестандартно и довольно долго. Обычно можно использовать один символ (возможно, - ) для обозначения пустого значения или просто передать пустую строку, например "" , если в противном случае это не допустимое значение параметр. Пустая строка также делает тест короче, просто используйте if [-n "$ 3"] .
  • Если есть только один необязательный флаг, или если они зависимы, так что у вас никогда не может быть OPTFLAG2, но не OPTFLAG1, то вы можете просто пропустить те, которые вы не хотите устанавливать. Если вы используете "" для пустых параметров, как предложено выше, вы в любом случае можете пропустить все завершающие пустые места.

Этот метод в значительной степени похож на способ передачи параметров компиляторам в Makefiles.

И снова - если входные данные могут содержать пробелы, это становится некрасивым.

0
27.01.2020, 19:52

используйте массив.

#!/bin/bash

args=( --flag1 "$1" --flag2 "$2" )
[  "x$3" = xFALSE ] ||  args+=( --optflag1 "$3" )
[  "x$4" = xFALSE ] ||  args+=( --optflag2 "$4" )
[  "x$5" = xFALSE ] ||  args+=( --optflag3 "$5" )
[  "x$6" = xFALSE ] ||  args+=( --optflag4 "$6" )
[  "x$7" = xFALSE ] ||  args+=( --optflag5 "$7" )

program_name "${args[@]}"

это позволит правильно обрабатывать аргументы с пробелами.

[edit] Я использовал примерно эквивалентный синтаксис args=("${args[@]}" --optflag1 "$3" ), но G-Man предложил лучший способ.

4
27.01.2020, 19:52

В сценарии оболочки аргументами являются «$ 1», «$ 2», «$ 3» и т. Д. аргументы $ #.
Если ваш сценарий не распознает параметры, вы можете не указывать определение параметров и рассматривать все аргументы как операнды.
Для распознавания параметров используйте встроенную функцию getopts

1
27.01.2020, 19:52

Теги

Похожие вопросы