Правильное использование переменных может придать сценариям дополнительную мощь и гибкость, а для этого необходимо изучить все тонкости и нюансы.
9.1. Внутренние переменные
путь к исполняемому файлу Bash
версия Bash, установленного в системе
содержимое вершины стека каталогов (который управляется командами pushd и popd)
Эта переменная соответствует команде dirs, за исключением того, что dirs показывает полное содержимое всего стека каталогов.
заданный по-умолчанию редактор, вызываемый скриптом, обычно vi или emacs.
«эффективный» идентификационный номер пользователя (Effective User ID)
Идентификационный номер пользователя, права которого были получены, возможно с помощью команды su.
имя текущей функции
группы, к которым принадлежит текущий пользователь
Это список групп (массив) идентификационных номеров групп для текущего пользователя, как эо записано в /etc/passwd.
домашний каталог пользователя, как правило это /home/username (см. Пример 9-13)
(Спасибо S. C., за разъяснения и примеры.)
Начиная с версии 2.05, Bash, в операциях подстановки имен файлов, не делает различий между символами верхнего и нижнего регистров, в диапазонах символов в квадратных скобках. Например,, ls [A-M]* выведет как File1.txt, так и file1.txt. Возврат к общепринятому стандарту поведения шаблонов в квадратных скобках выполняется установкой переменной LC_COLLATE в значение C командой export LC_COLLATE=C в файле /etc/profile и/или
Эта внутренняя переменная определяет кодировку символов. Используется в операциях подстановки и поиске по шаблону.
Номер строки исполняемого сценария. Эта переменная имеет смысл только внутри исполняемого сценария и чаще всего применяется в отладочных целях.
Идентификатор аппаратной архитектуры.
прежний рабочий каталог ( «OLD-Print-Working-Directory» )
тип операционной системы
путь поиска, как правило включает в себя каталоги /usr/bin/, /usr/X11R6/bin/, /usr/local/bin, и т.д.
Инструкция PATH=$:/opt/bin добавляет каталог /opt/bin в конец текущего пути поиска. Иногда может оказаться целесообразным, внутри сценария, временно добавить какой-либо каталог к пути поиска. По завершении работы скрипта, эти изменения будут утеряны (вспомните о том, что невозможно изменить переменные окружения вызывающего процесса).
Код возврата канала (конвейера). Интересно, что это не то же самое, что код возврата последней исполненной команды.
Если поместить эти строки в сценарий и исполнить его, то будут выведены верные значения 0 1 0.
Спасибо Wayne Pollock за замечания и предоставленный пример.
Сравните с командой pidof.
prompt, приглашение командной строки.
Третичное приглашение (prompt), выводится тогда, когда пользователь должен сделать выбор в операторе select (см. Пример 10-29).
рабочий (текущий) каталог
Аналог встроенной команды pwd.
переменная по-умолчанию, куда записывается ввод пользователя, выполненный с помощью команды read если явно не задана другая переменная. Так же может использоваться в операторе select, для построения меню выбора.
Время паботы сценария в секундах.
список допустимых опций интерпретатора shell. Переменная доступна только для чтения.
Уровень вложенности shell. Если в командной строке
дает 1, то в сценарии значение этой переменной будет больше на 1, т.е. 2.
Если переменная окружения $TMOUT содержит ненулевое значение, то интерпретатор будет ожидать ввод не более чем заданное число секунд, что, в первичном приглашении (см. описание PS1 выше), может привести к автоматическому завершению сеанса работы.
К сожалению это возможно только во время ожидания ввода с консоли или в окне терминала. А как было бы здорово, если бы можно было использовать эту внутреннюю переменную, скажем в комбинации с командой read! Но в данном контексте эта переменная абсолютно не применима и потому фактически бесполезна в сценариях. (Есть сведения о том, что в ksh время ожидания ввода командой read можно ограничить.)
Организация ограничения времени ожидания ввода от пользователя в сценариях возможна, но это требут довольно сложных махинаций. Как один из вариантов, можно предложить организовать прерывание цикла ожидания по сигналу. Но это потребует написание функции обработки сигналов командой trap (см. Пример 29-5).
Пример 9-2. Ограничения времени ожидания ввода
В качестве альтернативы можно использовать stty.
Пример 9-3. Еще один пример ограничения времени ожидания ввода от пользователя
Пример 9-4. Ограничение времени ожидания команды read
UID (идентификатор) текущего пользователя, в соответствии с /etc/passwd
Позиционные параметры (аргументы)
аргументы передаются. из командной строки в сценарий, функциям или команде set (см. Пример 4-5 и Пример 11-13)
Все аргументы в виде одной строки (слова)
Прочие специальные переменные
Список флагов, переданных сценарию (командой set). См. Пример 11-13.
PID последнего, запущенного в фоне, процесса
Специальная переменная, содержит последний аргумент предыдущей команды.
Пример 9-9. Переменная «подчеркивание»
Примечания
Слова «аргумент» и «параметр» очень часто используются как синонимы. В тексте данного документа, они применяются для обозначения одного и того же понятия, будь то аргумент, передаваемый скрипту из командной строки или входной параметр функции.
Убедитесь, что у вас установлена и настроена система на базе Linux. Мы будем работать над системой Ubuntu 20.04 Linux. Войдите в систему под учетной записью пользователя Ubuntu, чтобы начать работу над IFS. Будет лучше, если вы войдете в систему под своей учетной записью root. После входа в систему запустите терминал командной строки в своей системе из области «Действия».
Пример 01: IFS разделяет строку с использованием пробела в качестве значения
В нашем первом примере мы поймем концепцию разделения строки в bash при использовании пробела в качестве значения-разделителя с помощью переменной IFS. Во-первых, мы должны создать в нашей системе файл bash. Мы можем создавать новые файлы в нашей системе Linux с помощью команды touch. Как показано ниже, мы создали файл bash file1.sh с помощью инструкции touch:
Откройте домашний каталог вашей системы Linux, используя значок папки, отображаемый в левом углу рабочего стола Ubuntu 20.04. В нем вы найдете свой недавно созданный файл bash «file1.sh». Откройте файл «file1.sh» и введите приведенный ниже сценарий. Во-первых, мы определили строку с именем «str» с некоторым строковым значением в ней. Затем мы определяем переменную-разделитель IFS как переменную, имеющую в качестве значения пробел. После этого мы использовали оператор чтения для сохранения и чтения разделенных данных в массив strarr с помощью флага «-a». Оператор ‘echo’ используется для печати строки строки вместе с подсчетом общего количества слов в массиве с использованием “$<#strarr[*]>”. Цикл «for» используется для печати значений массива в разделенной форме с использованием переменной «var». Обратная косая черта «\n» использовалась в строке печати вместе с переменной «var», чтобы разделить одну строку после каждого значения массива. Сохраните сценарий с помощью клавиши «Ctrl+S» и закройте файл, чтобы продолжить.
Пример 02: IFS разделяет строку с использованием символа в качестве значения
В вышеупомянутом примере вы видели, как разбить строковые переменные на части, используя пробел в качестве разделителя IFS. Теперь мы будем использовать символ для разделения строки с помощью разделителя IFS. Откройте командный терминал и создайте новый файл bash «file2.sh» в домашнем каталоге системы Linux, используя команду touch следующим образом:
Откройте домашний каталог вашей системы Linux. Вы найдете в нем свой недавно созданный файл. Откройте только что созданный файл и напишите представленный ниже код на bash. В строке 3 мы инициировали оператор «echo» для печати строки. Следующая строка считывает данные, введенные пользователем в терминале с использованием ключевого слова read. Затем мы определили разделитель «IFS» и установили запятую «,» в качестве его символьного значения. Другой оператор «read» был определен для чтения и сохранения значений, разделенных запятыми, в строке, которая вводится пользователем в массив «strarr». Наконец, мы инициировали три оператора echo для печати значений разделения, разделенных запятыми, в виде переменных, как показано на изображении. Сохраните и закройте этот файл.
Теперь нам нужно запустить этот сохраненный файл. Выполните показанную ниже команду bash, за которой следует имя файла в терминале, чтобы сделать это. Вы должны добавить строковое значение, которое должно содержать запятую «,» внутри значений, и нажать кнопку Enter. Теперь ваши данные сохранены в массиве strarr. Последние три строки показывают вывод операторов «echo». Как видите, каждый текст до и после запятой использовался как отдельное значение.
Пример 03: IFS Split String
Мы сделали оба предыдущих примера в файле bash. Теперь у нас будет иллюстрация использования «IFS» без создания файла bash. Для этого откройте командную оболочку. Во-первых, нам нужно создать строку «var» со строковым значением в ней. Эта строка содержит запятые после каждого слова.
Затем инициализируйте переменную IFS с помощью символьной запятой в качестве значения разделителя.
После этого мы использовали цикл «for» для поиска каждого слова из переменной «var», разделенного запятой-разделителем IFS, и печати его с помощью оператора «echo».
У вас будет результат ниже. Он покажет каждое слово строковой переменной «var» на новой строке из-за запятой-разделителя «», используемой в качестве символа разделения.
Заключение:
В этой статье вы узнали о различных методах разделения входных значений в bash, например, с помощью пробела или символа. Мы надеемся, что иллюстрации, упомянутые в этой статье, помогут вам разбить каждую строку с помощью разделителя IFS.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Переменная jiffies Глобальная переменная jiffies содержит количество импульсов системного таймера, которые были получены со времени загрузки системы. При загрузке ядро устанавливает значение этого параметра в нуль и он увеличивается на единицу при каждом прерывании
Условная переменная
Условная переменная Одним из важнейших принципов использования мьютексов является максимальное сокращение размеров критической секции, то есть участка, который потоки должны проходить последовательно. Однако зачастую возникает необходимость ожидания выполнения
5.6.3 Переменная PATH
5.6.3 Переменная PATH Еще одна очень важная переменная имеет имя PATH. Она задает перечень путей к каталогам, в которых bash осуществляет поиск файлов (в частности, файлов с командами) в тех случаях, когда полный путь к файлу не задан в командной строке. Отдельные каталоги в этом
5.6.4 Переменная IFS
5.6.4 Переменная IFS Эта переменная задает разделители полей (Internal Field Separator), которые используются при операции разделения слов при преобразованиях командной строки, выполняемых оболочкой перед тем, как запустить командную строку на исполнение. Значение этой переменной по
Что содержит переменная перед тем, как ей присваивается значение?
Что содержит переменная перед тем, как ей присваивается значение? Во время выполнения процедуры VBA выделяет для каждой переменной из этой процедуры пространство в памяти и приписывает переменной начальное значение; означающее, что в переменной ничего не хранится. Чаще
Переменная FIREBIRD (или INTERBASE)
Переменная FIREBIRD (или INTERBASE) Если установлена переменная окружения FIREBIRD (INTERBASE для версии 1.0.x), то она используется и при инсталляции, и в процессе работы на всех платформах для указания корневого каталога сервера Firebird. Если она присутствует, то перекрываются все другие
Пожалуй, самый простой пример цикла for в bash-скриптах — это перебор списка простых значений:
Простой цикл for
Перебор сложных значений
Вот что получится после того, как этот цикл пройдётся по списку. Как видите, результат вполне ожидаем.
Перебор сложных значений TNW-CUS-FMP — промо-код на 10% скидку на наши услуги, доступен для активации в течение 7 дней»
Инициализация цикла списком, полученным из результатов работы команды
Ещё один способ инициализации цикла for заключается в передаче ему списка, который является результатом работы некоей команды. Тут используется подстановка команд для их исполнения и получения результатов их работы.
Цикл, который перебирает содержимое файла
Тут надо учесть, что подобный подход, если ожидается построчная обработка данных, не сработает для файла более сложной структуры, в строках которого может содержаться по несколько слов, разделённых пробелами. Цикл будет обрабатывать отдельные слова, а не строки.
Что, если это совсем не то, что нужно?
Разделители полей
Причина вышеописанной особенности заключается в специальной переменной окружения, которая называется IFS (Internal Field Separator) и позволяет указывать разделители полей. По умолчанию оболочка bash считает разделителями полей следующие символы:
После добавления этой команды в bash-скрипт, он будет работать как надо, игнорируя пробелы и знаки табуляции, считая разделителями полей лишь символы перевода строки.
Если этот скрипт запустить, он выведет именно то, что от него требуется, давая, в каждой итерации цикла, доступ к очередной строке, записанной в файл.
Построчный обход содержимого файла в цикле for
Обход файлов, содержащихся в директории
Один из самых распространённых вариантов использования циклов for в bash-скриптах заключается в обходе файлов, находящихся в некоей директории, и в обработке этих файлов.
Например, вот как можно вывести список файлов и папок:
Вот что выведет скрипт.
Вывод содержимого папки
Обратите внимание на то, как мы инициализируем цикл, а именно — на подстановочный знак «*» в конце адреса папки. Этот символ можно воспринимать как шаблон, означающий: «все файлы с любыми именами». он позволяет организовать автоматическую подстановку имён файлов, которые соответствуют шаблону.
Циклы for в стиле C
Если вы знакомы с языком программирования C, синтаксис описания bash-циклов for может показаться вам странным, так как привыкли вы, очевидно, к такому описанию циклов:
На bash это можно написать так:
А вот рабочий пример:
Этот код выведет список чисел от 1 до 10.
Работа цикла в стиле C
Цикл while
Вот схема организации циклов while while команда проверки условия do другие команды done
Взглянем на пример скрипта с таким циклом:
Результат работы цикла while
Вложенные циклы
В теле цикла можно использовать любые команды, в том числе — запускать другие циклы. Такие конструкции называют вложенными циклами:
Ниже показано то, что выведет этот скрипт. Как видно, сначала выполняется первая итерация внешнего цикла, потом — три итерации внутреннего, после его завершения снова в дело вступает внешний цикл, потом опять — внутренний.
Вложенные циклы
Обработка содержимого файла
Чаще всего вложенные циклы используют для обработки файлов. Так, внешний цикл занимается перебором строк файла, а внутренний уже работает с каждой строкой. Вот, например, как выглядит обработка файла /etc/passwd :
В этом скрипте два цикла. Первый проходится по строкам, используя в качестве разделителя знак перевода строки. Внутренний занят разбором строк, поля которых разделены двоеточиями.
Обработка данных файла
Такой подход можно использовать при обработке файлов формата CSV, или любых подобных файлов, записывая, по мере надобности, в переменную окружения IFS символ-разделитель.
Управление циклами
Возможно, после входа в цикл, нужно будет остановить его при достижении переменной цикла определённого значения, которое не соответствует изначально заданному условию окончания цикла. Надо ли будет в такой ситуации дожидаться нормального завершения цикла? Нет конечно, и в подобных случаях пригодятся следующие две команды:
Команда break
Досрочный выход из цикла for
Вот — то же самое, но уже для цикла while :
Команда continue
Когда в теле цикла встречается эта команда, текущая итерация завершается досрочно и начинается следующая, при этом выхода из цикла не происходит. Посмотрим на команду continue в цикле for :
Команда continue в цикле for
Обработка вывода, выполняемого в цикле
Например, вместо того, чтобы показывать на экране то, что выводится в цикле, можно записать всё это в файл или передать ещё куда-нибудь:
Перенаправление вывода цикла в файл
Пример: поиск исполняемых файлов
Поиск исполняемых файлов в папках из переменной PATH
Итоги
Сегодня мы поговорили о циклах for и while в bash-скриптах, о том, как их запускать, как ими управлять. Теперь вы умеете обрабатывать в циклах строки с разными разделителями, знаете, как перенаправлять данные, выведенные в циклах, в файлы, как просматривать и анализировать содержимое директорий.
Если предположить, что вы — разработчик bash-скриптов, который знает о них только то, что изложено в первой части этого цикла статей, и в этой, второй, то вы уже вполне можете написать кое-что полезное. Впереди — третья часть, разобравшись с которой, вы узнаете, как передавать bash-скриптам параметры и ключи командной строки, и что с этим всем делать.
Уважаемые читатели! В комментариях к предыдущему материалу вы рассказали нам много интересного. Уверены, всё это окажет неоценимую помощь тем, кто хочет научиться программировать для bash. Но тема эта огромна, поэтому снова просим знатоков поделиться опытом, а новичков — впечатлениями.
This variable is used in a few different places. The semantics vary slightly, for example:
Create a text file called /tmp/domains.txt as follows:
Create a shell script as follows:
Output for this script is:
example:
example:
There are special rules for handling whitespace characters in IFS, in any of the field-splitting situations above (the first three bullet points). Whitespace IFS characters at the beginning and end of a string are removed entirely (except in the special case noted above), and consecutive whitespace IFS characters inside a string are treated as a single delimiter. For example, consider the following:
In the first example, the gecos variable is assigned the empty string, which is the contents of the field between the two adjacent colons. The colons are not consolidated together; they are treated as separate delimiters. In the second example, the one variable gets the value 1, and the two variable gets the value 2. The leading whitespace is trimmed, and the internal whitespace is consolidated.
If IFS contains a mixture of whitespace and non-whitespace characters, it treats them differently. Any non-whitespace IFS character plus all adjacent IFS whitespace characters acts as a single field delimiter. (In addition, any sequence of one or more whitespace IFS characters also still counts.) For example:
The comma and space after this are treated as a field delimiter, The comma plus the multiple spaces around it after that are the second field delimiter. Finally, the single space after the is the final field delimiter, yielding a total of four words (fields).
More random examples:
The first example above shows the lack of splitting when IFS is empty. The second shows the last variable-name given to a read command absorbing all the remaining words of input. The third shows that splitting and delimiter-consolidation are not performed on the remaining part of a line when assigning excess fields to the last variable.
Here’s another look at having more input fields than variables. Note that out of the three consecutive colons which follow field 2, precisely one colon was removed in order to terminate field 2. The remaining two colons, as well as two more colons later on, were all left untouched, and assigned to variable c verbatim.
IFS variable syntax
Words of the form $’string’ are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.
When performing WordSplitting on an unquoted expansion, IFS is used to split the value of the expansion into multiple words.