Меню Рубрики

Аргументы командной строки linux

Аргументы командной строки Bash

Функциональность интерпретатора Bash позволяет работать не только со статистическими данными, записанными в скриптах. Иногда возникает необходимость добавить сценарию интерактивности, позволяя принимать внешние параметры скрипта для манипуляции ими в коде.

В этой статье будет рассмотрено, как принимать аргументы командной строки bash, способы его обработки, проверка опций, а также известные особенности при работе с ними.

Параметры скрипта Bash

Интерпретатор Bash присваивает специальным переменным все параметры, введённые в командной строке. В их состав включено название сценария, выполняемого интерпретатором. Такие переменные называются ещё числовыми переменными, так как в их названии содержится число:

  • $0 — название сценария;
  • $1 — первый параметр;
  • .
  • $9 — девятый параметр сценария.

Ниже приведён пример использования одного параметра скрипта Bash:

#!/bin/bash
factorial=1
for (( number = 1; number

Результат работы кода:

Переменная $1 может использоваться в коде точно так же, как и любая другая. Скрипт автоматически присваивает ей значение из параметра командой строки — пользователю не нужно делать это вручную.

Если необходимо ввести дополнительные параметры, их следует разделить в командной строке пробелами.

#!/bin/bash
total=$[ $1 * $2 ]
echo «Первый параметр равен $1.»
echo «Второй параметр равен $2.»
echo «Произведение параметров равно $total.»

Пример работы кода:

Командный интерпретатор присвоил числа 5 и 10 соответствующим переменным — $1 и $2.

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

#!/bin/bash
echo «Добро пожаловать, $1»

Пример работы кода:

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

Если необходимо использовать больше 9 параметров для скрипта, то названия переменных немного изменятся. Начиная с десятой переменной, число, стоящее после знака $, необходимо заключать в квадратные скобки (без внутренних пробелов):

#!/bin/bash
total=$[ $ <10>* $ <11>]
echo «Десятый параметр равен $<10>»
echo «Одиннадцатый параметр равен $<11>»
echo «Произведение этих параметров равно $total»

Пример работы кода:

Получение названия скрипта Bash

Как уже упоминалось, имя сценария является самым первым параметром скрипта. Чтобы определить название программы, используется переменная $0. Такая необходимость возникает, например, при написании скрипта, который может выполнять несколько функций. Однако при этом возникает одна особенность, которую нужно учитывать на практике:

#!/bin/bash
echo «Имя сценария: $0»

Пример работы кода:

Как видно, если строкой, фактически переданной в переменную $0, является весь путь к сценарию, то на вывод будет идти весь путь, а не только название программы.

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

Для этого специально предусмотрена небольшая команда. Команда basename возвращает только название скрипта без абсолютного или относительного пути к нему:

#!/bin/bash
name=`basename $0`
echo «Имя запущенной программы: $name»

Результат работы кода:

Проверка параметров скрипта

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

Если попробовать запустить написанный ранее скрипт test2 без аргументов, то перед выводом команд echo будет отображена ошибка:

Чтобы предотвращать подобные ситуации, необходимо действовать на упреждение — проверять аргументы скрипта на наличие значений. Это настоятельная рекомендация при использовании параметров в командной строке, и только после ревизии стоит пускать их в дело:

#!/bin/bash
if [ -n «$1» ]
then
echo «Добро пожаловать, $1»
else
echo «Простите, вы не представились»
fi

Пример работы кода:

В данном случае использовалась опция -n из предыдущей статьи о сравнении строк в Bash для проверки на наличие значения в переменной, которая считала параметр.

Обработка неизветсного числа параметров

Для начала рассмотрим один из часто используемых инструментов при работе с параметрами Bash — команду shift. Её прямое назначение заключается в сдвиге параметров на одну позицию влево. Таким образом, значение из переменной $3 переместится в $2, а из $2 — в $1. Но из $1 значение просто отбросится и не сместится в $0, так как там неизменно хранится название запущенной программы.

Эта команда является эффективным способом обработки всех параметров, переданных сценарию, особенно, когда нельзя заранее узнать их количество. Достаточно лишь обработать $1, сделать сдвиг и повторить процедуру.

#!/bin/bash
count=1
while [ -n «$1» ]
do
echo «Параметр №$count = $1»
count=$[ $count + 1 ]
shift
done

Пример работы кода:

Этот скрипт выполняет цикл while, в условии которого указана проверка первого параметра на длину. И если она равна нулю, цикл прерывает свою работу. При положительном результате проверки команда shift сдвигает все параметры влево на одну позицию.

Ещё один вариант использование shift — смещать на несколько позиций. Для этого достаточно через пробел указать количество, на которое будет смещён ряд параметров скрипта.

#!/bin/bash
echo «Первый параметр из переданных: $1»
shift 2
echo «Теперь первый параметр: $1»

Пример работы скрипта:

На заметку: при использовании shift нужно быть осторожным, ведь сдвинутые за пределы $1 параметры не восстанавливаются в период работы программы.

Обработка опций в Bash

Помимо параметров скрипт может принимать опции — значения, состоящие из одной буквы, перед которыми пишется дефис. Рассмотрим 3 метода работы с ними в скриптах. Сперва кажется, что при работе с опциями не должно возникать каких-либо сложностей. Они должны быть заданы после имени запускаемой программы, как и параметры. При необходимости можно сделать обработку опций командной строки по такому же принципу, как это делается с параметрами.

По примеру выше можно применять shift для обработки простых опций. С помощью инструкции case можно определять, являются ли аргументы Bash опциями:

#!/bin/bash
while [ -n «$1» ]
do
case «$1» in
-a | -b | -c) echo «Найдена опция $1» ;;
*) echo «$1 не опция» ;;
esac
shift
done

Пример работы программы:

Блок case работает правильно вне зависимости от того, как расположены аргументы командной строки bash.

Выводы

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

Команда basename используется для обрезания пути запущенного сценария, что часто необходимо для создания гибких программ. Использование команды shift позволяет эффективно проходить по переданным скрипту параметрам, особенно когда их количество неизвестно.

Источник

Bash-скрипты, часть 3: параметры и ключи командной строки

Освоив предыдущие части этой серии материалов, вы узнали о том, что такое bash-скрипты, как их писать, как управлять потоком выполнения программы, как работать с файлами. Сегодня мы поговорим о том, как добавить скриптам интерактивности, оснастив их возможностями по получению данных от пользователя и по обработке этих данных.

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

В данном примере сценарию передано два параметра — «10» и «20». Всё это хорошо, но как прочесть данные в скрипте?

Чтение параметров командной строки

Оболочка bash назначает специальным переменным, называемым позиционными параметрами, введённые при вызове скрипта параметры командной строки:

  • $0 — имя скрипта.
  • $1 — первый параметр.
  • $2 — второй параметр — и так далее, вплоть до переменной $9 , в которую попадает девятый параметр.

Вот как можно использовать параметры командной строки в скрипте с помощью этих переменных:

Запустим сценарий с параметрами:

Вот что он выведет в консоль.

Вывод параметров, с которыми запущен скрипт

Обратите внимание на то, что параметры командной строки разделяются пробелами.

Взглянем на ещё один пример использования параметров. Тут мы найдём сумму чисел, переданных сценарию:

Запустим скрипт и проверим результат вычислений.

Сценарий, который находит сумму переданных ему чисел

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

Он выведет то, что мы от него ожидаем.

Сценарий, работающий со строковым параметром

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

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

Проверка параметров

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

Вызовем скрипт сначала с параметром, а потом без параметров.

Вызов скрипта, проверяющего наличие параметров командной строки

Подсчёт параметров

В скрипте можно подсчитать количество переданных ему параметров. Оболочка bash предоставляет для этого специальную переменную. А именно, переменная $# содержит количество параметров, переданных сценарию при вызове.

В результате скрипт сообщит о том, что ему передано 5 параметров.

Подсчёт количества параметров в скрипте

Эта переменная даёт необычный способ получения последнего из переданных скрипту параметров, не требующий знания их количества. Вот как это выглядит:

Вызовем скрипт и посмотрим, что он выведет.

Обращение к последнему параметру

Захват всех параметров командной строки

В некоторых случаях нужно захватить все параметры, переданные скрипту. Для этого можно воспользоваться переменными $* и $@ . Обе они содержат все параметры командной строки, что делает возможным доступ к тому, что передано сценарию, без использования позиционных параметров.

Переменная $* содержит все параметры, введённые в командной строке, в виде единого «слова».

В переменной $@ параметры разбиты на отдельные «слова». Эти параметры можно перебирать в циклах.

Рассмотрим разницу между этими переменными на примерах. Сначала взглянем на их содержимое:

Как видно, при выводе обеих переменных получается одно и то же. Теперь попробуем пройтись по содержимому этих переменных в циклах для того, чтобы увидеть разницу между ними:

Взгляните на то, что скрипт вывел в консоль. Разница между переменными вполне очевидна.

Разбор переменных $* и $@ в цикле

Переменная $* содержит все переданные скрипту параметры как единый фрагмент данных, в то время как в переменной $@ они представлены самостоятельными значениями. Какой именно переменной воспользоваться — зависит от того, что именно нужно в конкретном сценарии.

Команда shift

Использовать команду shift в bash-скриптах следует с осторожностью, так как она, в прямом смысле слова, сдвигает значения позиционных параметров.

Когда вы используете эту команду, она, по умолчанию, сдвигает значения позиционных параметров влево. Например, значение переменной $3 становится значением переменной $2 , значение $2 переходит в $1 , а то, что было до этого в $1, теряется. Обратите внимание на то, что при этом значение переменной $0 , содержащей имя скрипта, не меняется.

Воспользовавшись командой shift , рассмотрим ещё один способ перебора переданных скрипту параметров:

Скрипт задействует цикл while , проверяя длину значения первого параметра. Когда длина станет равна нулю, происходит выход из цикла. После проверки первого параметра и вывода его на экран, вызывается команда shift , которая сдвигает значения параметров на одну позицию.

Использование команды shift для перебора параметров

Используя команду shift , помните о том, что при каждом её вызове значение переменной $1 безвозвратно теряется.

Ключи командной строки

Ключи командной строки обычно выглядят как буквы, перед которыми ставится тире. Они служат для управления сценариями. Рассмотрим такой пример:

И проанализируем то, что он выведет в терминал.

Обработка ключей в скрипте

В этом коде использована конструкция case , которая сверяет переданный ей ключ со списком обрабатываемых скриптом ключей. Если переданное значение нашлось в этом списке, выполняется соответствующая ветвь кода. Если при вызове скрипта будет использован любой ключ, обработка которого не предусмотрена, будет исполнена ветвь «*».

Как различать ключи и параметры

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

Эта последовательность — двойное тире (—). Оболочка использует её для указания позиции, на которой заканчивается список ключей. После того, как скрипт обнаружит признак окончания ключей, то, что осталось, можно, не опасаясь ошибок, обрабатывать как параметры, а не как ключи. Рассмотрим пример:

Этот сценарий использует команду break для прерывания цикла while при обнаружении в строке двойного тире.

Вот что получится после его вызова.

Обработка ключей и параметров командной строки

Как видно, когда скрипт, разбирая переданные ему данные, находит двойное тире, он завершает обработку ключей и считает всё, что ещё не обработано, параметрами.

Обработка ключей со значениями

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

Скрипт должен уметь определять, когда вместе с ключами командной строки используются дополнительные параметры:

Вызовем этот скрипт в таком виде:

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

Обработка параметров ключей

В данном примере в конструкции case обрабатываются три ключа. Ключ -b требует наличия дополнительного параметра. Так как обрабатываемый ключ находится в переменной $1 , соответствующий ему параметр будет находиться в $2 (тут используется команда shift , поэтому, по мере обработки, всё, что передано сценарию, сдвигается влево). Когда с этим мы разобрались, осталось лишь извлечь значение переменной $2 и у нас будет параметр нужного ключа. Конечно, тут понадобится ещё одна команда shift для того, чтобы следующий ключ попал в $1 .

Использование стандартных ключей

При написании bash-скриптов вы можете выбирать любые буквы для ключей командной строки и произвольно задавать реакцию скрипта на эти ключи. Однако, в мире Linux значения некоторых ключей стали чем-то вроде стандарта, которого полезно придерживаться. Вот список этих ключей:

-a Вывести все объекты.
-c Произвести подсчёт.
-d Указать директорию.
-e Развернуть объект.
-f Указать файл, из которого нужно прочитать данные.
-h Вывести справку по команде.
-i Игнорировать регистр символов.
-l Выполнить полноформатный вывод данных.
-n Использовать неинтерактивный (пакетный) режим.
-o Позволяет указать файл, в который нужно перенаправить вывод.
-q Выполнить скрипт в quiet-режиме.
-r Обрабатывать папки и файлы рекурсивно.
-s Выполнить скрипт в silent-режиме.
-v Выполнить многословный вывод.
-x Исключить объект.
-y Ответить «yes» на все вопросы.

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

Получение данных от пользователя

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

Иногда сценарии нуждаются в данных, которые пользователь должен ввести во время выполнения программы. Именно для этой цели в оболочке bash имеется команда read .

Эта команда позволяет принимать введённые данные либо со стандартного ввода (с клавиатуры), либо используя другие дескрипторы файлов. После получения данных, эта команда помещает их в переменную:

Обратите внимание на то, что команда echo , которая выводит приглашение, вызывается с ключом -n . Это приводит к тому, что в конце приглашения не выводится знак перевода строки, что позволяет пользователю скрипта вводить данные там же, где расположено приглашение, а не на следующей строке.

Обработка пользовательского ввода

При вызове read можно указывать и несколько переменных:

Вот что выведет скрипт после запуска.

Несколько переменных в команде read

Если, вызвав read , не указывать переменную, данные, введённые пользователем, будут помещены в специальную переменную среды REPLY :

Использование переменной среды REPLY

Если скрипт должен продолжать выполнение независимо от того, введёт пользователь какие-то данные или нет, вызывая команду read можно воспользоваться ключом -t . А именно, параметр ключа задаёт время ожидания ввода в секундах:

Если данные не будут введены в течение 5 секунд, скрипт выполнит ветвь условного оператора else , выведя извинения.

Ограничение времени на ввод данных

Ввод паролей

Иногда то, что вводит пользователь в ответ на вопрос скрипта, лучше на экране не показывать. Например, так обычно делают, запрашивая пароли. Ключ -s команды read предотвращает отображение на экране данных, вводимых с клавиатуры. На самом деле, данные выводятся, но команда read делает цвет текста таким же, как цвет фона.

Вот как отработает этот скрипт.

Ввод конфиденциальных данных

Чтение данных из файла

Команда read может, при каждом вызове, читать одну строку текста из файла. Когда в файле больше не останется непрочитанных строк, она просто остановится. Если нужно получить в скрипте всё содержимое файла, можно, с помощью конвейера, передать результаты вызова команды cat для файла, конструкции while , которая содержит команду read (конечно, использование команды cat выглядит примитивно, но наша цель — показать всё максимально просто, ориентируясь на новичков; опытные пользователи, уверены, это поймут).

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

Посмотрим на него в деле.

Чтение данных из файла

Тут мы передали в цикл while содержимое файла и перебрали все строки этого файла, выводя номер и содержимое каждой из них.

Итоги

Сегодня мы разобрали работу с ключами и параметрами командной строки. Без этих средств диапазон использования скриптов оказывается чрезвычайно узким. Даже если скрипт написан, что называется, «для себя». Тут же мы рассмотрели подходы к получению данных от пользователя во время выполнения программы — это делает сценарии интерактивными.

В следующий раз поговорим об операциях ввода и вывода.

Уважаемые читатели! Спасибо вам за то, что делитесь опытом в комментариях к предыдущим частям этого цикла материалов. Если вам есть что сказать об обработке всего того, что можно передать в скрипт при запуске или во время его работы, уверены, многим будет интересно об этом почитать.

Похожие публикации

Bash-скрипты, часть 6: функции и разработка библиотек

Bash-скрипты, часть 5: сигналы, фоновые задачи, управление сценариями

Bash-скрипты, часть 4: ввод и вывод

Комментарии 23

Обратите внимание на то, что параметры командной строки разделяются пробелами.

Нет! Параметры (любые, а не только options/arguments) коммандной строки разделяются всеми символами из «Input field separator» и хранятся в переменной IFS.
По дефолту, ЕМНИП это пробел, таб и перенос строки.

Тут мы передали в цикл while содержимое файла и перебрали все строки этого файла, выводя номер и содержимое каждой из них.

Нет! Вы передали содержимое файла в сабшел, внутри которого запустили цикл while. Принципиальная разница обсужадалсь мной и г-н selivanov_pavel в комментариях к предыдущей статье. Ветка вот этого комментария: https://habrahabr.ru/company/ruvds/blog/325928/#comment_10161776

/bin/bash в шебанге не исправили, ветка вот этого комментария: https://habrahabr.ru/company/ruvds/blog/325928/#comment_10161110

Стилистику кода оставили как есть не смотря на замечания.

И это вещи, которые бросились в глаза быстрым пролистыванием.
Зачем делиться опытом в комментариях, если он не перетекает в другие статьи?

P.S. Я понимаю что это перевод другой работы, но я ещё раз повторяю — работа кишит граблями которые не оговариваются и про которые в комментариях указывается начиная с первой статьи. Пожалуйста перестаньте распространять эти грабли дальше. Вносите исправления тогда уж с учётом комментариев…

За пример теста аргументов приведённый в статье надо бить по рукам. Никогда так не делайте!
Если скрипту не передали аргумент, то $1 вообще не “установлена”, мне интересно сколько людей словило фейспалм над явным использованием неинициализированной переменной.
Устанавливается флаг который проверяет все переменные и выдаёт ошибку в случае unset variable

Правильно проверять на количество входных аргументов используя технику из части Подсчёт параметров или используя default value в случае отсутствия.
Например так:

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

logging — отдельная функция которая принимает два параметра — severity и message.

P.P.S. Обещаю больше не плодить по несколько комментариев за раз. Просто не хочу чтобы несведущие читатели таких статей ломали себе зубы об 1000 раз пройденные вещи.
Будь автор перевода человеком в моей команде, он тут же получит к прочтению «O’Reilly — Classic Shell Scripting» и Bash TLDP. Если же автор перевода все мной описанные грабли и так знает, то какого чёрта эти грабли не исправляются?!

Если скрипту не передали аргумент, то $1 вообще не “установлена”, мне интересно сколько людей словило фейспалм над явным использованием неинициализированной переменной.

В bash не такого понятия, как «неинициализированная переменная». «Не установленная» (unset/not set) — есть, но такие всегда пусты, если вы не используете странные вещи вроде set -u . «Пустая переменная == неустановленная переменная» — это концепция с долгой историей: насколько мне известно, существуют системы, в которых переменная окружения в принципе не может быть удалена, но может быть переписана. Поэтому использование [[ -n «$1» ]] вполне допустимо и идиоматично, а использование set -u вызывает сомнение в вашей адекватности.

Последнее потому, что вы можете написать MY_OPTION_PASSED_THROUGH_ENVIRONMENT= my_script , чтобы временно «удалить» некую настройку и ожидать, что скрипт будет работать как будто она не установлена. Но эквивалента для временного удаления просто нет (только subshell и unset, не слишком удобно), а скрипт с set -u просто провоцирует нарушать конвенцию «пустая == неустановленная».

И заметьте, что тот же $ <1:-foo>сделает подстановку foo, если 1 не установлена, либо пуста. А чего‐то, что делает подстановку, если переменная не установлена нет. В zsh вот зачем‐то есть ( $ <1-foo>), а в bash и POSIX оболочках нет.

Хотя я не снимаю свою позицию по поводу set -u , вообще‐то я слишком быстро пошёл писать негативный комментарий: относительно входных параметров вы полностью правы, концепция в гораздо меньшей степени касается их: точно так же как бо́льшинство скриптов и программ обработают пустые переменные окружения как отсутствующие, ожидается, что пустой входной параметр будет обработан как пустой входной параметр. Подозреваю, что причиной тому является то, как легче всего писать код обработки на C.

Тем не менее, код [[ «$<1:-unset>» == «unset» ]] ещё хуже кода [[ -n «$<1>» ]] : мало того, что вы обрабатываете пустую переменную как неопределённую вопреки тому, против чего предостерегали, так ещё и лишаете пользователя возможности использовать строку unset в качестве параметра. Никогда не пишите такой код.

$ <1:-foo>сделает подстановку foo, если 1 не установлена, либо пуста. А чего‐то, что делает подстановку, если переменная не установлена нет

«Пустая переменная == неустановленная переменная»

мало того, что вы обрабатываете пустую переменную как неопределённую вопреки тому, против чего предостерегали, так ещё и лишаете пользователя возможности использовать строку unset в качестве параметра

Гм, в man zsh эта конструкция явно прописана. А в man bash это спрятано в параграфе перед конструкциями («отсутствие двоеточия приводит к тесту на только неустановленные переменные»), в стандарте так же, только написано после перечисления различных $ штук.

Сам факт наличия вышеупомянутых конструкций, разделяющих empty и unset опровергает это утверждение. Найдёте ссылку на источник? Интересно будет почитать.

Я в основном по опыту говорю: в tutorial’ах обычно именно так, C’шный код того же Vim явным образом превращает пустые в неустановленные (использует NULL, когда p != NULL && *p == NUL с однозначным комментарием «empty is the same as not set»).

Если вдуматься, то данная конструкция именно что обрабатывает оба случая. Если ничего не прилетит (unset) — дефолт, если прилетит что-то пустое (empty/null) — например скрипт вызывают с переменной, которая оказалась без значения — дефолт. Про слово «unset» в качестве default word — с вашей стороны просто придирка. Это был пример, текст можно использовать другой по желанию + я ещё не видел скрипта которому надо было передавать именно такой параметр (вы видели хоть раз в жизни?) + это сделано для повышения читабельности, где слово unset явно выражает что эта конструкция проверяет и зачем. Всё равно хотите делать тест -n? Напишите вот так:

Если у вас по $1 имя команды, то это нормально. А если там имя файла, то нужно предполагать, что туда запихнут любую дичь, включая $’./my\nmultiline\nstring’ , даже если её туда ни в жизнь в реальности не запихнут. unset — это корректное имя файла, которое даже не начинается с дефисоминуса, значит оно должно обрабатываться как имя файла.

[[ -n «$<1:->» ]] — это тот же [[ -n «$1» ]] для set -u , чище использовать вариант с $# , но не использовать set -u из‐за проблем с «unset = empty».

В препоследний абзац вы что-то напихали всего сразу докучи.
Как проверка [[ -n «$1» ]] спасёт от той самой «дичи»? Правильно, никак, собственно и мной приведённые вещи. Это уже должны быть дополнительные проверки после того как выянится что входной параметр вообще есть.
Я же вроде уже написал для чего и почему в примере используется слово unset, не говоря о том, что слово настолько редкое, что что-бы получить файл с таким именем, это должно быть что-то очень специфическое и в таком случае можно написать unsetvar или один из массы других вариантов. Пожалуйста, перестаньте пытаться притянуть это за уши.

Таки да, я разьве не это написал? Абзацем выше явно сказано что вариант с заменой-дефолта для улучшения читаемости.

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

Это «не что‐то специфическое», это «ожидаемое поведение для всех аргументов соответствующих одному классу». «unset» вполне вписывается в типичный шаблон для имён файлов¹. Я не вижу никакой легальной причины сделать так, чтобы любое из легальных имён файлов не могло стоять на этой позиции. Даже если оно маловероятно.

И зачем вы зациклились на именах файлов, пусть я и привёл их в качестве примера? Может вы так забаните регулярное выражение для поиска по кодовой базе, оно и здесь также «настолько редкое»? Просто не нужно на пустом месте увеличивать количество специальных значений в полтора раза: пустое, неустановленное и «unset» ; вы не знаете заранее, не потребуется ли оно.

¹ В моём понимании для них ожидается, что всё подпадающее под ^(?!-)(?=.)(\.<0,2>/+)?([^/]+/(/+(. ))?)*[^/+]$ будет именем файла, возможно и что‐то сверх: file , ./file , ../path/to/file , /absolute/path/to/file , /////path//////to/////file .

Увы, нет. Автор скрипта должен знать когда и как правильно использовать подсчёт длины аргументов. В нашем обсуждаемом случае с «пустым» аргументом оно не сработает:

Я не понимаю, что здесь обсуждается. Моё мнение, основанное на том, как работает большинство утилит (особенно, написанных на C) — пустой параметр, переданный в скрипт — это пустое значение того, что должно быть на этом месте, а не отсутствие параметра. Пустая переменная окружения, содержащая настройки для программы — это то же, что неустановленная. В таком случае в вашем примере «Taking in!» — это ожидаемый вывод, но с set -u неудобно работать в режиме «пустая переменная окружения = неустановленной переменной окружения», потому что придётся писать везде :- .

Непозиционные ( -p , —long-param ) сюда не относятся, но такое обрабатывается всегда отдельно. Правда, в моих коротких скриптах, часто через if [[ «$1» = «—param» ]] ; then shift ; do_something ; fi , что не совсем корректно.

Хотя, если ваш стиль кодирования предполагает, что все переменные с настройками должны получить значение по‐умолчанию, пусть даже оно и пустое, в одном месте, где‐то наверху, то с set -u будет легче писать: в отличие от переменных‐настроек, для локальных переменных функций unset = empty будет маскировать ошибки. Мне начинает казаться, что это может быть лучше моей сложившейся практики и уже не выглядит дичью. Но почему‐то скриптов с set -u я просто ни разу не видел.

Кстати, вот что с поддержкой C’шных функций работы с окружениям по стандартам, согласно их man ам:

(un)setenv: 4.3BSD, POSIX.1-2001
putenv: POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD
getenv: SVr4, POSIX.1-2001, 4.3BSD, C89, C99

При этом если у вас только putenv и getenv то ничего из окружения удалить штатными средствами вы не можете. «Нештатными» (т.е. поддерживать свой environ и писать туда/читать оттуда, его же отдавать в execve) сможете, но это сильно усложнит код.

Как пример системы без unsetenv нашёл Solaris 8.

Each line that the shell reads from the standard input or a script is called a pipeline; it contains one or more commands separated by zero or more pipe characters (|). For each pipeline it reads, the shell breaks it up into commands, sets up the I/O for the pipeline, then does the following for each command:

1. Splits the command into tokens that are separated by the fixed set of metacharacters: SPACE, TAB, NEWLINE, ;, (, ), , |, and &. Types of tokens include words, keywords, I/O redirectors, and semicolons.

9. Takes the parts of the line that resulted from parameter, command, and arithmetic substitution and splits them into words again. This time it uses the characters in $IFS as delimiters instead of the set of metacharacters in Step 1.

Не описан такой вариант read:

while read x; do
echo $x
done

Ключ -s команды read предотвращает отображение на экране данных, вводимых с клавиатуры. На самом деле, данные выводятся, но команда read делает цвет текста таким же, как цвет фона.

Как вариант еще можно использовать аргументы формата key=value

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

  • Установка openoffice на mac os
  • Установка mac os через wifi
  • Установка mac os через transmac
  • Установка mac os через boot disk utility
  • Установка mac os с помощью r drive image