Меню Рубрики

Как написать в консоли флаг

Как написать в консоли флаг

Флаги командной строки это популярный способ указывать опции для консольных программ. К примеру, в команде wc -l -l является флагом командной строки.

В Go есть пакет flag , обеспечивающий базовые функции для работы с флагами. Мы будем использовать этот пакет для нашей демонстрационной консольной программы.

Базовые определения флагов доступны для типов string, integer и boolean. Тут мы определяем флаг-строку word со значением по-умолчанию «foo» и коротким описанием. Функция flag.String возвращает указатель на строку (а не саму строку); мы посмотрим, как использовать этот указатель ниже.

Тут мы декларируем флаги numb и fork , используя аналогичный подход, как и с флагом word .

Также флаги можно определять, используя существующую переменную, объявленную ранее в программе. Обратите внимание, что мы передаем в функцию указатель.

Как только все флаги определены, вызываем flag.Parse() , чтобы выполнить непосредственно разбор командной строки.

Тут мы выводим на экран считанные значения флагов, и оставшиеся аргументы командной строки. Обратите внимание. что мы должны разыменовывать указатель, *wordPtr , например, чтобы получить реальные значения.

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

Попробуйте запустить собранную программу, сначала указав значения для всех флагов.

Заметьте, если вы пропустите какие-то флаги, они будут равны значениям по-умолчанию.

Оставшиеся элементы командной строки будут выведены в конце.

Обратите внимание, что пакет flag требует, чтобы все флаги были указаны до оставшихся элементов командной строки. В противном случае, флаги будут обработаны как оставшиеся аргументы.

Используйте флаги -h или —help , чтобы вывести на экран автоматически сгенерированное текст с описанием флагов.

Если вы укажете флаг, который не был указан в программе, то flag выдаст сообщение об ошибке и текст со всеми возможными флагами.

Далее мы познакомимся с переменными окружения, еще одним способом параметризации программ.

Источник статьи: http://gobyexample.ru/command-line-flags.html

Как написать в консоли флаг

14.2.1. Разбор флагов в командной строке

Для разбора командной строки чаще всего применяется библиотека getoptlong (библиотека getopts.rb , обладающая менее развитой функциональностью, считается устаревшей). Она понимает однобуквенные и длинные флаги и распознает двойной дефис ( — ) как признак конца флагов. В целом библиотека ведет себя так же, как соответствующие функции GNU.

Необходимо создать объект класса GetoptLong , который и будет выполнять функции анализатора. Затем ему передаются допустимые значения флагов, а он извлекает их по одному.

У объекта-анализатора есть метод set_options , который принимает список массивов. Каждый массив содержит один или несколько флагов (в виде строк) и один «признак наличия аргумента», который говорит, должны ли эти флаги сопровождаться аргументами. Все флаги в одном массиве считаются синонимами; первый из них является «каноническим именем», которое и возвращает операция get .

Предположим, что имеется программа, понимающая следующие флаги: -h или —help (печать справки), -f или —file (указание имени файла), -l или —lines (вывод не более указанного числа строк, по умолчанию 100).

Такая программа могла бы начинаться следующим образом:

require «getoptlong»
parser = GetoptLong.new
parser.set_options(
[«-h», «—help», GetoptLong::NO_ARGUMENT],
[«-f», «—file», GetoptLong::REQUIRED_ARGUMENT],
[«-l», «—lines», GetoptLong::OPTIONAL_ARGUMENT])

Теперь можно в цикле вызвать метод get (см. листинг 14.1). Наличие операторных скобок begin-end имитирует цикл с проверкой условия в конце. У метода get есть синоним get_option , существуют также итераторы each и each_option , которые в точности идентичны.

Листинг 14.1. Получение флагов из командной строки

filename = nil
lines = 0 # По умолчанию вывод не усекается.
loop do
begin
opt, arg = parser.get
break if not opt
# Только для отладки.
puts (opt +» => » + arg)
case opt
when «-h»
puts «Usage: . »
break # Прекратить обработку, если задан флаг -h.
when «-f»
filename = arg # Запомнить аргумент — имя файла.
when «-l»
if arg != «»
lines = arg # Запомнить аргумент — число строк (если задан).
else
lines = 100 # Оставляемое по умолчанию число строк.
end
end
rescue => err
puts err
break
end
end
puts «имя файла = #»
puts «число строк = #«

Метод get возвращает nil , если флаг отсутствует, но пустую строку, если для флага не задан аргумент. Возможно, это ошибка.

В этом примере мы перехватываем исключения. Всего их может быть четыре:

• AmbiguousOption — указано сокращенное длинное имя флага, но сокращение не уникально;

Источник статьи: http://wm-help.net/lib/b/book/827961078/440

22. Команды управления флагами i8086

Статья основана на материале xrnd с сайта asmworld (из учебного курса по программированию на ассемблер 16-битного процессора 8086 под DOS).

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

Как вы, наверно, помните флаги изменяются в результате выполнения арифметических и логических команд, а также команд сдвига. Регистр флагов можно сохранить в стек с помощью команды PUSHF и восстановить из стека с помощью команды POPF. Кроме того, в процессоре существуют специальные команды, которые позволяют явно установить или сбросить флаги CF, DF и IF. Это очень простые команды: у них нет операндов и результатом является только изменение значения соответствующего флага.

Флаг переноса CF

Команда CLC сбрасывает флаг CF.

Команда STC устанавливает флаг CF в единицу.

Команда CMC инвертирует значение флага CF.

Флаг направления DF

Этот флаг определяет направление обработки данных цепочечными командами (о них подробно расскажу в отдельной статье). Он должен устанавливаться или сбрасываться перед использованием этих команд.

Команда CLD сбрасывает флаг DF.

Команда STD устанавливает флаг DF в единицу.

Флаг прерывания IF

Этот флаг определяет, разрешены в данный момент прерывания или нет (о прерываниях тоже будет отдельная статья).

Команда CLI сбрасывает флаг IF (запрещает прерывания).

Команда STI устанавливает флаг IF в единицу (разрешает прерывания).

Команды LAHF и SAHF

Команда LAHF загружает младший байт регистра флагов в AH. Её удобно использовать, когда нужно получить значения сразу нескольких флагов. Порядок расположения флагов представлен на рисунке:

Команда SAHF выполняет обратную операцию — загружает содержимое AH в младший байт регистра флагов. Это позволяет одновременно изменить значения нескольких флагов. При этом биты 1, 3, 5 регистра AH игнорируются.

Пример программы

В качестве примера использования команды LAHF я написал процедуру, которая получает и выводит на консоль значения флагов SF, ZF, AF, PF и CF. Подобную процедуру можно использовать в отладочных целях. Достаточно добавить её вызов в то место программы, где хочется проверить состояние флагов.

Чтобы выводить значения отдельных битов удобно написать отдельную процедурку для печати флага CF в виде символа. Нужный бит будет помещаться в флаг CF при помощи команды сдвига SHL.

А вот собственно процедура вывода флагов. Как видите, здесь нет ничего сложного 🙂 Процедура сохраняет регистр флагов и восстанавливает его перед возвратом управления, поэтому можно вызывать её где угодно, не волнуясь, что она нарушит выполнение основной программы.

Полный исходный код примера:

Вывод программы выглядит так:

Упражнение

Чтобы потренироваться в работе с флагами напишите следующую программу. Вычислите сумму значений флагов CF, SF, ZF и выведите на консоль результат сложения. Если результат больше 1, инвертируйте значение флага CF.

Источник статьи: http://pro-prof.com/forums/topic/asm_i8086_22

Использование пакета Flag в Go

Введение

Утилиты командной строки редко можно использовать в готовом виде без дополнительной настройки. Хорошие значения по умолчанию очень важны, однако полезные утилиты должны принимать конфигурацию от пользователей. В большинстве платформ утилиты командной строки принимают флаги для настройки выполнения команд. Флаги — это ограниченные значениями ключей строки, добавляемые после имени команды. Go позволяет настраивать утилиты командной строки, принимающие флаги посредством пакета flag из стандартной библиотеки.

В этом обучающем руководстве мы покажем различные способы использования пакета flag для построения различных видов утилит командной строки. Флаги используются для контроля вывода программы, ввода аргументов позиционирования с сочетанием флагов и других данных, а также для реализации субкоманд.

Использование флага для изменения поведения программы

Использование пакета flag предусматривает три шага. Вначале определяются переменные для сбора значений флагов, затем определяются флаги для использования приложением Go, и в заключение производится проверка синтаксиса флагов, переданных приложению при выполнении. Большинство функций в пакете flag связаны с определением флагов и их привязке к определенным вами переменным. Синтаксическая проверка выполняется функцией Parse().

Для иллюстрации мы создадим программу, определяющую флаг Boolean для изменения сообщения, которое потом выводится стандартным способом. Если используется флаг -color , программа выводит сообщение синим цветом. Если флаг не указан, сообщение выводится без цветов.

Создайте новый файл с именем boolean.go :

Добавьте в файл следующий код для создания программы:

В этом примере используются управляющие последовательности ANSI, предписывающие терминалу выводить цветной текст. Это специальные последовательности символов, поэтому для них полезно определить новый тип. В этом примере мы присвоили типу имя Color и определили его как string . Затем мы определили палитру цветов для использования в следующем блоке const . Функция colorize , определяемая после блока const , принимает одну из констант Color и переменную string для сообщения, которому назначается цвет. Затем она предписывает терминалу изменить цвет, сначала выводя управляющую последовательность для запрошенного цвета, а затем выводя сообщение, и, наконец, запрашивает сброс цвета терминала посредством вывода специальной последовательности сброса цвета.

В main мы используем функцию flag.Bool для определения флага логического оператора с именем color . Второй параметр этой функции, false , задает значение этого флага по умолчанию, если оно отсутствует. Хотя вы можете ожидать иного, установка значения true не меняет поведения, так как при задании флага оно становится ложным. Поэтому этот параметр почти всегда будет иметь значение false с флагами логических операторов.

Последний параметр — это строка документации, которая может быть выведена как сообщение об использовании. Возвращаемое этой функцией значение представляет собой указатель на bool . Функция flag.Parse на следующей строке использует этот указатель, чтобы задать переменную bool на базе флагов, передаваемых пользователем. Мы сможем проверить значение этого указателя bool , сняв ссылку на указатель. Дополнительную информацию о переменных указателей можно найти в обучающем руководстве по указателям. Используя это логическое значение, мы можем вызывать функцию colorize , если флаг -color установлен, и вызывать переменную fmt.Println , если флаг отсутствует.

Сохраните файл и запустите программу без флагов:

Вывод должен выглядеть так:

Теперь запустите эту программу еще раз с помощью флага -color :

При этом также будет выведен текст, но при этом синим цветом.

Флаги — не единственные значения, которые передаются командам. Также вы можете отправлять имена файлов или другие данные.

Работа с позиционными аргументами

Обычно команды принимают несколько аргументов, которые выступают в качестве субъекта фокуса команды. Например, команда head , которая распечатывает первые строки файла, часто вызывается как head example.txt . Файл example.txt представляет собой позиционный аргумент вызова команды head .

Функция Parse() продолжает выполнять синтаксическую проверку появляющихся флагов, пока не обнаружит аргумент, не являющийся флагом. Пакет flag делает их доступными через функции Args() и Arg() .

В качестве иллюстрации построим упрощенную реализацию команды head , отображающей первые несколько строк указанного файла:

Создайте новый файл head.go и добавьте следующий код:

Вначале мы определяем переменную count , где будет храниться количество строк, которое программа должна считывать из файла. Мы определяем флаг -n , используя flag.IntVar , что отражает поведение первоначальной программы head . Эта функция позволяет нам передать собственный указатель в переменную в отличие от функций flag , у которых нет суффикса Var . Помимо этой разницы остальные параметры flag.IntVar соответствуют параметрам flag.Int : имя флага, значение по умолчанию и описание. Как и в предыдущем примере, мы вызовем flag.Parse() для обработки пользовательских данных.

Следующий раздел выполняет чтение файла. Мы определим переменную io.Reader , для которой будет задан запрошенный пользователем файл или которой будут передаваться стандартные входные данные программы. В выражении if мы используем функцию flag.Arg для доступа к первому аргументу после всех флагов. Если пользователь указал имя файла, оно будет задано. В противном случае, это будет пустая строка ( «» ). Если имя файла имеется в наличии, мы используем функцию os.Open для открытия файла и задаем предварительно определенный для этого файла io.Reader . В противном случае мы используем os.Stdin для считывания стандартных исходных данных.

В заключительном разделе используется *bufio.Scanner , созданный с помощью bufio.NewScanner , для считывания строк из переменной io.Reader in . Мы проводим итерацию до значения count в цикле for и вызываем break , если при сканировании строчки buf.Scan получается значение false , показывающее, что количество строчек меньше, чем запрошенное пользователем.

Запустите эту программу и выведите содержимое записанного файла, используя head.go в качестве аргумента файла:

Разделитель — представляет собой специальный флаг, который распознается пакетом flag и показывает, что за ним не идут другие аргументы флагов. При запуске этой команды выводится следующее:

Используйте определенный вами флаг -n для изменения объема выводимых данных:

Так выводится только выражение пакета:

Наконец, если программа определяет отсутствие аргументов позиции, она считывает исходные данные из стандартного источника, как и команда head . Попробуйте запустить следующую команду:

Результат должен выглядеть так:

Поведение функций flag , которое мы наблюдали, ограничено исследованием вызова всей команды. Такое поведение требуется не всегда, особенно если вы пишете инструмент командной строки, поддерживающий субкоманды.

Использование FlagSet для реализации субкоманд

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

Приложения Go могут поддерживать субкоманды с собственным набором флагов, используя оператор типа flag.( *FlagSet) . Для иллюстрации мы создадим программу, которая будет реализовать команду, используя две субкоманды с разными флагами.

Создайте новый файл с именем subcommand.go и добавьте в него следующий код:

Эта программа разделена на несколько частей: функция main , функция root и отдельные функции для реализации субкоманды. Функция main обрабатывает ошибки, возвращаемые командами. Если любая функция возвращает ошибку, выражение if определит ее, распечатает ошибку и закроет программу с кодом состояния 1 , сообщающим операционной системе о возникновении ошибки. Внутри функции main мы передаем все аргументы вызова программы в функцию root . Удалим первый аргумент, представляющий собой имя программы (в предыдущих примерах ./subcommand ), выделив срез os.Args.

Функция root определяет []Runner , где определяются все субкоманды. Runner — это интерфейс субкоманд, позволяющий функции root получить имя субкоманды с помощью Name() и сравнить его с содержанием переменной subcommand . После обнаружения правильной субкоманды посредством итерации переменной cmds мы инициализируем субкоманду с остальными аргументами и вызываем метод Run() для этой команды.

Мы определяем только одну субкоманду, хотя данная структура позволяет легко создавать и другие команды. Экземпляр GreetCommand создается с помощью NewGreetCommand при создани нового *flag.FlagSet с помощью flag.NewFlagSet . flag.NewFlagSet принимает два аргумента: имя набора флагов и стратегию отчета об ошибках проверки синтаксиса. Имя *flag.FlagSet доступно с помощью flag.( *FlagSet). Метод Name. Мы используем этот метод в (*GreetCommand). Name() так, что имя субкоманды соответствует имени, которое мы присвоили *flag.FlagSet . NewGreetCommand также определяет флаг -name аналогично предыдущим примерам, но вместо этого вызывает его как метод поля *flag.FlagSet *GreetCommand , gc.fs . Когда функция root вызывает метод Init() команды *GreetCommand , мы передаем указанные аргументы методу Parse поля *flag.FlagSet .

Субкоманды будет проще увидеть, если вы соберете эту программу и запустите ее. Выполните сборку программы:

Теперь запустите программу без аргументов:

Вы увидите следующий результат:

Теперь запустите команду с субкомандой greet :

Результат будет выглядеть следующим образом:

Теперь используйте флаг -name с greet для указания имени:

Программа выведет следующее:

В этом примере проиллюстрированы некоторые принципы структурирования больших приложений командной строки в Go. Наборы FlagSet разработаны так, чтобы дать разработчикам больше контроля над местом и способом обработки флагов логикой синтаксической проверки флагов.

Заключение

Флаги делают приложения более полезными в разных условиях, поскольку они дают пользователям контроль над способом выполнения программы. Очень важно дать пользователям полезные параметры по умолчанию, но также следует дать им возможностям изменять параметры, которые не подходят для их конкретной ситуации. Вы увидели, что пакет flag предоставляет вашим пользователям гибкие возможности выбора конфигурации. Вы можете выбрать несколько простых флагов или создать разветвленный набор субкоманд. В любом случае, использование пакета flag поможет вам выполнить сборку утилит в стиле длинной истории гибких инструментов командной строки с поддержкой сценариев.

Ознакомьтесь с серией статей по программированию на Go, чтобы узнать больше о языке программирования Go.

Источник статьи: http://www.digitalocean.com/community/tutorials/how-to-use-the-flag-package-in-go-ru


0 0 голоса
Article Rating
Подписаться
Уведомить о
guest

0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии