Кармический блог быдлокодера

Мониторим домены

Небольшой скрипт на php для мониторинга освободившихся доменов в помощь лентяям.

 

<?php

$domains = array(
    'domain1.ru',
    'domain2.ru'
);

$email = 'my@email.com';

foreach($domains as $domain)
{
    $inf = check_domain($domain);
    if(!isset($inf['free-date']))
    {
        $text = 'DOMAIN ' . $domain . ' FREE';
        mail($email,$text, $text);
    }
}

function check_domain( $domain )
{
    $curl = curl_init();
    curl_setopt( $curl, CURLOPT_URL,'r01.ru/domain/whois/check-domain.php?domain=' . $domain);
    curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
    curl_setopt($curl,CURLOPT_FOLLOWLOCATION,true);
    $result = curl_exec($curl);
    $info = array();
    $infoField = array(
        'free-date',
        // 'domain','type','descr','state','nic-hdl','person','phone','fax-no','e-mail','reg-till','created','changed', 'registrar'
    );
    foreach($infoField as $field)
    {
        preg_match('#' . $field . ': (.*)#',$result,$m);
        $info[$field] = isset($m[1]) ? strip_tags($m[1]) : '';
    }
    return $info;
}

Запускать скрипт по крону, раз в 5-10 минут.

PS Письма по-умолчанию будут падать в спам.

Групповое переименование файлов по маске

По долгу службы встала задача переименовать группу файлов в директории по маске ( убрать у php файлов префикс и постфикс ).
Исходные файлы вида aqNameClass.class.php нужно привести к виду NameClass.php

Решается эта задача одной командой shell:

 for i in *.class.php; do mv "$i" `echo "$i" | sed "s/\.class//" | sed "s/^aq//"`; done 

Unix – это круто =)

Монтирование SD карты с правами пользователя в arch linux

Задача:

примонтировать SD карту на 64G как дополнительный жесткий диск, чтобы не-root мог читать ее и записывать в нее.

Решение:

mount -o uid=<uid> /dev/<dev_id> /mnt/<mount_point>

где,

<uid> — id пользователя ( узнать можно командой id или посмотреть в /etc/passwd )

<dev_id> — устройство sd карты

<mount_point> — каталог в который будет примонтирована SD-карта.

в /etc/fstab добавляем опцию монтированя uid=<uid>

и всё.

Zsh

[announce]Справка по zsh. Пусть будет тут на всякий случай.[/announce]

Введение

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

Zsh — командный процессор UNIX, который может использоваться как в качестве командного процессора для скриптов, так и в качестве интерактивной оболочки. Zsh обладает множеством возможностей, среди которых — настраиваемый механизм дополнений (completions), редактирование командной строки, механизм сохранения историй, встроенное исправление неправильных команд.

По возможностям Zsh наибольшее сходство имеет с ksh, но при этом еще обладает множеством расширений.

Свежие версии Zsh доступны с сервера www.zsh.org и его зеркал. Кроме этого, Zsh часто включают в состав популярных дистрибутивов Linux и других вариантов UNIX.

Запуск

Обычно Zsh указывают в качестве интерактивной оболочки для входа в систему. Но, кроме этого, Zsh можно запускать и отдельно, с разными ключами, определяющими его поведение. Например, ключ -r заставляет Zsh работать в «ограниченном» (restricted) режиме, ключ -c указывает откуда читать команды для выполнения, а ключ -i заставляет работать в интерактивном режиме.

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

При запуске Zsh старается эмулировать sh или ksh в зависимости от того, под каким именем его запустили. В режиме эмуляции не исполняются обычные скрипты инициализации и завершения работы Zsh. Для инициализации используются файлы /etc/profile и $HOME/.profile

Файлы, используемые при запуске

При запуске Zsh читается некоторое количество файлов, содержащих команды инициализации. В первую очередь читается файл /etc/zshenv, затем читается файл $ZDOTDIR/.zshenv. Затем, если запускаемый процесс используется для входа в систему, то читаются файлы /etc/zprofile и $ZDOTDIR/.zprofile. Затем, если оболочка является интерактивной, читаются файлы /etc/zshrc и $ZDOTDIR/.zshrc. И наконец, если процесс используется для входа в систему, то читаются файлы /etc/zlogin и $ZDOTDIR/.zlogin.

Когда происходит выход из оболочки, использовавшейся для входа в систему, то читаются файлы $ZDOTDIR/.zlogout и затем /etc/zlogout.

Если переменная ZDOTDIR не установлена, то вместо нее используется значение переменной HOME. Файл /etc/zshenv читается при запуске любого процесса Zsh, поэтому он должен быть настолько малым, насколько это возможно.

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

Грамматика команд

Грамматика команд по большей части совпадает с грамматикой других командных процессоров семейства bourne shell, хотя имеются различные расширения, специфические для данного командного процессора. Схожесть грамматики позволяет быстро перейти к работе с использованием Zsh, и осваивать новые возможности уже в процессе его эксплуатации.

Перенаправление вывода

Zsh поддерживает такое же перенаправление вывода как и bash, но кроме этого он поддерживает множество расширений. Некоторые расширения работают только если заданы соответствующие настройки. Например, если не задана опция CLOBBER, то использование команды > для существующего файла приведет к возникновению ошибки и невыполнению команды. На этот случай, для практически всех команд существуют их модификации, которые не зависят от настроек. Например, для команды > существуют ее модификации >! и >|.

Для одновременного перенаправления стандартного вывода и стандартного потока сообщений об ошибках определены дополнительные команды >&, &>, >>&, &>> и их модификации со знаками | и ! (например, &>|). Эти команды соответственно переписывают и дополняют информацию в указанных файлах, а также позволяют избавиться от неуклюжих конструкций вида 1>FNAME 2>&1.

Zsh также позволяет перенаправлять информацию в более чем в один файл, аналогично использованию команды tee (это доступно только если определена переменная MULTIOS, что обычно указано по умолчанию). Кроме этого можно одновременно использовать перенаправление и конвейеры. Например, команда date >foo | cat запишет дату в файл foo и выведет ее в стандартный поток вывода.

Если установлена переменная MULTIOS, то имя файла, указанное в качестве того, куда надо будет перенаправлять информацию, подвергается раскрытию шаблонов (globbing). Таким образом можно использовать команду

# : > *

для усечения всех файлов в текущем каталоге.

Множественное перенаправление также работает и при вводе информации, позволяя заменять конструкции вида

# cat foo fubar | sort

на конструкции

# sort <foo <fubar

или даже

# sort <f{oo,ubar}

Zsh даже позволяет использовать перенаправление без указания команды. Если не установлена переменная NULLCMD, то при таком использовании будет возникать ошибка. Но если установлена переменная NULLCMD, или READNULLCMD (она имеет преимущество над NULLCMD), то эти команды будут использоваться для обработки данных. По умолчанию NULLCMD имеет значением команду cat, а READNULLCMD значением команду more. Таким образом команда

# < file

приведет к показу указанного файла.

Функции

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

Для ускорения загрузки Zsh может использовать автоматически загружаемые функции, когда они только объявляются, но не считываются. При первом использовании такой функции происходит ее считывание и компиляция. Для объявления автоматически загружаемой функции используется встроенная команда autoload (или ее налоги functions -u и typeset -fu). Поиск определений функций осуществляется по каталогам, перечисленным в переменной fpath.

Кроме обычных функций, Zsh позволяет определять функции со специальным значением. Так, например, функция chpwd вызывается при изменении рабочего каталога, а функции precmd и preexec выполняются перед каждым выводом приглашения и перед выполнением считанной команды соответственно. Кроме того, может быть определена функция periodic, которая может выполнятся через каждые $PERIOD (если этот параметр определен) секунд перед выводом приглашения.

Задания

Zsh работает с задачами подобно bash, но при этом имеется возможность более гибко работать с заданиями запущенными в фоновом режиме. Кроме команды &, которая используется для запуска задачи в фоновом режиме, также определены команды &| или &!, которые запускают программу таким образом, что она не будет иметь записи в таблице задач и с которой нельзя будет работать обычными функциями работы с заданиями.

Для ссылки на задания можно использовать специальные переменные: %NUMBER — для ссылки на задание номер NUMBER (как в bash); %STRING и %?STRING — для ссылки на задания, чьи командные строки начинаются и содержат строку STRING соответственно; %% (или %+) и %- для ссылки на текущее и предыдущее задание.

Подстановка переменных

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

Подстановки в строке приглашения

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

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

Полное описание всех возможных подстановок для строки приглашения можно найти в справке по Zsh.

Темы для строки приглашения

Благодаря возможностям Zsh пользователи пишут различные модули расширений. Одним из таких модулей является модуль для установки тем для строк приглашения. Этот модуль загружается с помощью команд:

# autoload -U promptinit

# promptinit

и позволяет пользователям использовать заранее подготовленные темы приглашений. Команда prompt -p выдает примеры всех установленных тем строки приглашения.

Прочие подстановки

Все остальные подстановки выполняются в пять шагов, в перечисленном ниже порядке:

  • Сначала выполняются подстановки в истории. На этом этапе подставляются строки из истории, которые соответствуют заданным командам. См. раздел Подстановки истории.
  • Затем выполняется раскрытие псевдонимов (алиасов). Раскрытие алиасов выполняется немедленно, до того, как командная строка будет разобрана.
  • Затем выполняется подстановка процессов, параметров, команд, раскрытие арифметических выражений, и затем уже раскрытие выражений в скобках. Каждый из этих этапов подробно описан в справке по Zsh.
  • Раскрытие имен файлов. На этом этапе происходит подстановка комбинаций строк и чисел с символом ~. Если используется комбинация с числом, то каталог берется из стека каталогов. Если после символа ~ задается строка, то эта строка будет использоваться как имя пользователя, и вместо сочетания ~ со строкой подставляется домашний каталог соответствующего пользователя.
  • И на последнем шаге происходит генерация имен файлов (globbing). См. раздел Генерация имен файлов.

Полный перечень всех шаблонов и настроек вы сможете найти в справке по Zsh.

Подстановки истории

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

Подстановки истории Zsh позволяют указать какое слово из команды нужно задействовать. Для этого используются следующие указатели слов:

:0
первое слово в командной строке;
:n
n-й аргумент;
:^
1-й аргумент (аналогично :1);
:$
последний аргумент строки;
:X-Y
аргументы с X по Y;
:X-
все аргументы начиная с X кроме последнего;
:*
все аргументы;
:X*
все аргументы начиная с X (аналогично :X-$).

Кроме этого, в подстановках истории после указателей слов можно использовать модификаторы, которые позволяют выполнять различные подстановки в истории. Так, например, модификатор :h работает подобно использованию команды dirname, а модификатор :t работает подобно команде basename. Полный список модификаторов можно получить в руководстве по Zsh.

Генерация имен файлов

Zsh предоставляет множество дополнений и настроек по генерации имен файлов.

Операторы глоббинга

Кроме стандартных символов (таких как *, ?, [...]), используемых для генерации имен файлов в других командных процессорах, в Zsh определены дополнительные операторы глоббинга, такие как:

^X
совпадает с любым кроме X. Например, ^*.elc будет соответствовать всем файлам, кроме тех которые указаны в маске (в нашем случае это файлы с расширением .elc);
X~Y
совпадает со всем, что соответствует шаблону X, и не соответствует шаблону Y. Например, *.el*~*.elc соответствует всем файлам, чье расширение начинается с .el, но при этом не будут учитываться файлы с расширением *.elc;
X#
соответствует нулю или нескольким вхождениям шаблона X;
X##
соответствует одному или нескольким вхождениям шаблона X.

Флаги глоббинга

Флаги глоббинга используются для воздействия на шаблон, который стоит правее указанного флага. Все флаги имеют форму (#X), где X определяет нужный модификатор. Ниже приведено описание нескольких флагов, которые могут наиболее часто использоваться в работе:

i
делает шаблон независимым от регистра символов, которые в нем применяются;
l
заставляет символы в нижнем регистре, которые используются в шаблоне, соответствовать символам и в вернем и нижнем регистре. Символы в верхнем регистре, будут соответствовать точно тем же символам;
I
локально отменяет воздействие флагов l и i;

Другие флаги, описаны в руководстве по Zsh.

Квалификаторы глоббинга

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

.
для указания обычных файлов,
/
для указания каталогов,
=
для указания сокетов,

и многие другие (можно указывать права доступа, времена модификации файлов и т.п.). Их полное описание можно найти в руководстве по Zsh.

Рекурсивный глоббинг

Zsh позволяет производить рекурсивное раскрытие имен файлов. Для этого используются формы **/ и ***/ Первая форма отличается от второй лишь тем, что не следует по символьным ссылкам. Так, например:

# ls **/foo

произведет поиск файлов с именем foo во всех подкаталогах.

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

Кроме вышеперечисленных настроек. Zsh также позволяет использовать приблизительное соответствие, пытаясь найти файлы, в именах которых (по его мнению :-) могли бы быть сделаны ошибки.

Параметры и настройки

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

Параметры

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

Для объявления типов параметров или присвоения целого или строкового значения параметру, используется встроенная команда typeset. Значения строкового или целого типа могут присваиваться простым приравниванием — ИМЯ=ЗНАЧЕНИЕ. Для присваивания других типов параметров используется команда typeset.

Позиционные параметры используются для доступа к аргументам командной строки для функции или скрипта командного процессора. Специальные параметры *, @ и argv являются массивами, которые содержат все позиционные параметры. Позиционные параметры могут быть изменены после запуска скрипта или функции с помощью встроенной команды set.

Настройки

Настройки устанавливаются с помощью встроенной команды setopt, а удаляются с помощью команды unsetopt. Список настроек приведен в документации по Zsh.

Дополнения (completitions)

Дополнения обеспечивают набор строк за вас. Они могут быть в разных формах, но для их выполнения (обычно) используется клавиша TAB.

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

Виджеты дополнений

Виджеты дополнений определяются с помощью ключа -C встроенной команды zle, которая предоставляется модулем zsh/zle.

Дополнения с использованием compctl

Данный метод аналогичен по настройке тем дополнениям, что применяются в csh & tcsh и является устаревшим, так что новые пользователи скорее всего предпочтут использовать другие методы определения дополнений, но он все равно поддерживается текущими версиями Zsh.

Задание дополнений с помощью данного метода имеет общую форму:

# compctl ключи [command ...]

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

Ключи определяют типы параметров, которые будут подпадать под дополнение (ключи командной строки, списки выполняемых заданий, и т.п.).

Ключ -k указывает, что параметры, которые будут дополняться, будут переданы в массиве. Это ключ очень полезен, когда у вас списки параметров приведены в файле, или заданы в явной форме. Так, можно явно задать список серверов, имена которых будут дополняться при использовании команды ssh:

# compctl -k "( server1 server2 )" ssh

В том случае, если у вас много серверов, то вы можете перечислить их в файле и вместо явного перечисления указать в скобках команду для получения содержимого нужного файла (в нашем примере пусть это будет ~/.servers):

# compctl -k "( ` cat ~/.servers ` )" ssh

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

Другие ключи команды compctl описаны в справочном руководстве по Zsh.

Подсистема дополнений

Эта подсистема является новой и введена начиная с версии 4.0. При этом для пользователей остается доступной старая подсистема дополнений с использованием команды compctl, однако можно запретить ее использование с помощью команды:

# zstyle ':completion:*' use-compctl false

Основным отличием новой системы дополнений от старой является то, что вместо того, чтобы задавать все настройки разом при запуске командного процессора, соответствующие части кода будут вызываться только тогда, когда будет нажата клавиша TAB, при этом будут генерироваться новые дополнения. Также введены новые команды, которые заменяют использование команды compctl с разными ключами, например, для задания списка дополнений должна использоваться команда compadd.

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

Полное описание всех возможностей новой системы дополнений можно найти в руководстве пользователя Zsh.

Модули Zsh

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

Загрузка модулей производится с помощью команды zmodload. Например, для загрузки модуля редактирования командной строки zle будет использоваться команда

# zmodload zsh/zle

Модуль редактирования командной строки (zsh/zle)

Данный модуль предоставляет пользователю возможность редактирования командной строки. Редактирование может осуществляться в одном из двух режимов — многострочном, если терминал поддерживает перемещение между строками и однострочном, если терминал не поддерживает перемещения между строками или установлена опция SINGLE_LINE_ZLE.

Привязки клавиш

Модуль редактирования поддерживает концепцию таблиц привязки клавиш (keymaps). В любой момент времени может существовать любое количество таблиц привязки. По умолчанию в Zsh определены 4 таблицы привязки клавиш, которые эмулируют команды Emacs, редактора vi в режиме вставки, редактора vi в режиме команд, а также специальный режим safe, которые не определяет никаких привязок, кроме вставки символов соответствующих клавишам.

Встроенные команды zle

Модуль zle предоставляет пользователю некоторое количество встроенных команд. Сюда относятся команды привязки клавиш — bindkey, которая позволяет определять и переопределять сочетания клавиш; команды управления виджетами zle — создания, удаления, выдачи списка и другие.

Виджеты zle

Все действия в модуле редактирования выполняются через виджеты. Задачей виджета является выполнение какой-то простой операции. Все клавиши привязываются к какому-то из виджетов. Виджеты могут быть встроенные или определенные пользователем.

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

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

Модуль zsh/zftp

Данный модуль позволяет пользователю выполнять команды ftp в командной строке или внутри скриптов. Интерфейс похож на тот, который используется в традиционном клиенте ftp, но при этом используются все возможности Zsh — дополнения, глоббинг и редактирование. Загрузка данного модуля предоставляет пользователю одну встроенную команду — zftp, с помощью которой и выполняются все операции.

Загрузка модуля выполняется с помощью команд:

# autoload -U zfinit
# zfinit

Встроенная команда zftp обеспечивает выполнение всех команд. Синтаксис команды выглядит следующим образом:

# zftp подкоманда [аргументы]

Подкомандами являются обычные команды ftpopen, cd, get, put, bin и другие. Кроме того, модуль предоставляет другие команды, которые являются алиасами для команд «zftp подкоманда«, такие как zfopen, zfget, zfcd и другие.

Другие модули Zsh

Кроме вышеперечисленных модулей, в поставку Zsh входят модули работы со списками привилегий POSIX.1e (модуль zsh/cap), работы с математическими функциями (модуль zsh/mathfunc), модуль использования некоторых стандартных команд (chown, chgrp, ln, rm и других) как встроенных (модуль zsh/files) и другие модули. Для получения их полного списка и описания работы с ними смотрите документацию из поставки Zsh.

Дополнительные источники информации

Вы можете найти дополнительную информацию о Zsh используя следующие ресурсы:

Источник: http://alexott.net/ru/writings/zsh/

Запись звука в Linux

[announce]Запись звука в Linux из консоли.[/announce]
На моём субноуте есть микрофон, вот подумал, что неплохобы понять как записывать снимать звук с него, вот что нашёл:

Запись в wav:
$ arecord test.wav Переконвертировать wav в mp3 можно вот так:
$ cat test.wav | lame — > test.mp3
или сразу создать mp3
$ arecord | lame — > test.mp3

Вот так можно записать ядро системы linux в mp3 :)
$ cat /boot/mykernel.img > /dev/dsp & arecord | lame — > test.mp3

Получить снимок с web камеры через консоль Linux

[announce]Вот способ получисть снимок с web камеры из шел.[/announce]
Искал способ как получить снимок (фото) с web камеры
Наткнулся только на статью про видеозахват через — ffmpeg. Вот ссылка — http://www.newmoldova.com/?q=node/85

Почитав немного ман по ffmpeg попробовал вот такую конструкцию:

$ ffmpeg -f video4linux2 -s 1024×768 -i /dev/video0 -f image2 snapshot.jpg 2>/dev/null

Вроде работает :)
-f video2linux — формат видео для захвата
-s 1024×768 — размер кадра захвата
-i /dev/video0 — файла web камеры
-f image2 snapshot.jpg — выходной тим и имя файла

Ещё документация по shell

[announce]Вот более хорошая дока по shell.[/announce]

 

		 ПРОГРАММИРОВАНИЕ НА shell (UNIX)

		       (Учебное пособие)



(с) А. Соловьев



			 1. ВВЕДЕНИЕ



     Среди операционных систем особое место занимает Unix.

     Беспрецедентным  является  то,  что  ОС  Unix может работать

практически  на  на  всех  выпускаемых  платформах.  UNIX  -  это

стандарт  де  факто  открытых  и  мобильных опрерационных систем.

(поскольку название UNIX запатентовано компанией AT&T - различные

юниксы  называются  различно:  SCO  UNIX,  BSDI,  Solaris, Linux,

DG/UX, AIX и т.д.).

     Это  не  только  многозадачная,  но  и многопользовательская

система.  Она обеспечивает современный пользовательский интерфейс

на  базе системы  X Window и межмашинную связь на базе протоколов

TCP/IP и т.п.

     ОС Unix была создана Кеном Томпсоном и Деннисом Ритчи в Bell

Laborotories  (AT&T).  Широко распространяться Unix/v7 (версия 7)

начала  в  79  - 80-м годах. Вручение создателям Unix в 1983 году

Международной   премии   А.Тьюринга  в  области  программирования

ознаменовало  признание  этой  системы  мировой научной (computer

science) общественностью. Что также беспрецедентно.

     Сколько  операционных  систем взошло и зашло на компьютерном

небосклоне за время существования UNIX!



     ОС  Unix  стоит  на  трех  китах: язык Си, файловая система,

командный  язык. В дальнейшем к ним добавились система X Window и

протоколы TCP/IP.

     Язык  Си,  на  котором написана сама операционная система, с

одной  стороны,  сочетает  в себе свойства языка высокого уровня:

описание  типов, программные структуры if, for, while и т.п., а с

другой   -  содержит  средства,  присущие  обычно  языкам  уровня

ассемблера:    регистровые   переменные,   адресную   (ссылочную)

арифметику, возможности работы с полями бит и отдельными битами и

т.п.



		     2. ФАЙЛОВАЯ СИСТЕМА



     Файловая  система  ОС Unix имеет иерархическую (древовидную)

структуру. В вершинах дерева находятся каталоги (используют также

термины - справочники, директории), содержащие списки файлов. Эти

файлы  в  свою  очередь  могут  быть  либо снова каталогами, либо

обычными  файлами,  либо  специальными  файлами,  представляющими

различные утройства ввода-вывода.



			  /

			  |

   -----------------------------------------------------------

  |     |     |    |    |    |    |                 |    |     |

bin    boot  dev  etc  lib  mnt  sys    .   .   .  tmp  unix  usr





     Kорневой каталог имеет имя "/". Он обычно содержит каталоги:



     bin - для наиболее используемых команд;

     usr  -  каталоги  и  обычные  файлы,  содержащие информацию,

привлекаемую при решении задач пользователя;

     dev  -  для  специальных  файлов,  представляющих устройства

(дисплеи, диски...);

     etc - для хранения команд администратора системы;

     lib - важнейшие библиотеки;

     mnt  -  для  подключения  (примонтирования)  новых  файловых

систем;

     sys - средства для изменения конфигурации системы;

     tmp - для хранения временных файлов;

     usr  -  каталоги  и  обычные  файлы,  содержащие информацию,

привлекаемую при решении задач пользователя.



А также обычные (выполняемые) файлы:

     unix - ядро;

     boot - загрузчик.



     Полные имена файлов будут: /bin, /usr, ..., /unix, /boot.



     В   свою  очередь  эти  каталоги  могут  содержать  каталоги

следующего   уровня.  Например,  каталог  "usr",  кроме  прочего,

содержит каталоги:

     bin - хранит дополнительные команды;

     games - игры;

     include - хранит фрагменты системных программ;

     lib - хранит дополнительные библиотеки.

полные имена этих файлов будут:



     /usr/bin   /usr/games   /usr/include   /usr/lib



     Если  в  каталоге  "/usr/include"  содержится каталог "sys",

который  в  свою  очередь, содержит каталог "conf", то полное имя

файла "conf" будет



     /usr/include/sys/conf



     Формальным  признаком  полного  имени  является  то, что оно

начинается со слэша ("/").

     Относительное  имя  начинается  не  с  "/",  и определят имя

относительно  своего местоположения. Если (пользовател?) в данный

момент  находится в директории /usr файловой системы, то он может

обратиться к этому же файлу по относительному имени



	 include/sys/conf



     Есть  два  специальных  имени:

     .   -  это "имя" текущего директория  и

     ..  -  это "имя" родительского директория (т.е. директория,

находящегося на ступеньку выше данного на пути к корню).

     В  качестве  имени  файла  как  правило может использоваться

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

использоваться  и  другие  символы,  однако ряд этих символов при

использованнии в имени требует специального экранирования. (Лучше

не  пользоваться  специальными  символами  в  именах - иногда это

может привести к сложностям в обращении к таким именам, поскольку

спецсимволы могут иметь в shell некоторый специальный смысл).

     В  ряде  систем  длина  имени  ограничивается 14-ю символами

(этого  ограничения  желательно  придерживаться для переносимости

файлов), однако в других системах допускаются более длинные имена

- например, до 256 символов.

     В   общем   случае   не  явлются  обязательными  и  какие-то

расширения  в  именах.  Хотя ряд команд требуют наличия некоторых

фиксированных  расширений  в именах, например расширение ".с" для

исходных файлов для Си-компилятора.

     КСТАТИ.  В  ОС UNIX большие и маленькие буквы воспринимаются

как  различные,  поэтому  "FILE",  "file"  и  "File"  -  это  три

различных имени!



     ВАЖНОЕ  ЗАМЕЧАНИЕ.  Отдельные  части  файловой системы могут

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

нескольких жестких и гибких дисках (или в различных частях одного

диска).  Соответсвующие  фрагменты  (поддеревья файловой системы)

монтируются  (присоединяются)  в единую файловую систему командой

mount  (обычно  это  функция  администратора системы), после чего

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

в имени никак не отражается устройство, на котором файл находится

или создается (т.е. никаких "A:").



     Командный  язык ОС Unix - shell оперирует с командами. Более

подробно о нем разговор далее, а пока рассмотрим несколько команд

работы с файловой системой.

     Например, в результате выполнения команды



	    ls -l /usr



     где ls - имя команды; -l - флаг, говорящий о том, что выдача

должна  быть  в длинном формате; /usr -имя каталога, который надо

echo. На экран будет выведено



    drwxrwxr-x  2  root  2048  nov 3  12:11  bin

    -rwxr--r--  1  root   861  may 11 20:11  boot

    drwxrwxr-x  2  root  1024  jan 9  11:55  dev

    drwxrwxr-x  1  root  4096  may 11 20:11  dos

    drw-r--r--  3  root  4096  nov 17 12:01  include

    drwxr-xr-x  7  root  480   nov 17 12:30  lib



     Первая  строка  означает, что это каталог (d-directory), где

первая триада "rwx" разрешает владельцу каталога: r - читать, w -

писать  и  х  - выполнять (более точно, для файлов типа каталог w

означает  разрешение  создавать  файлы в каталоге и удалять их из

него,  а  х разрешает доступ к файлам каталога); членам группы, в

которую  входит  владелец,  также  разрешены  все  три  операции.

Последняя  триада  отражает  права  доступа прочих пользователей,

которым  разрешено  только читать и выполнять (запрещено писать в

этот файл, т.е. изменять содержимое каталога).

     Далее,  2  -  это  число связей файла (т.е. где-то в системе

есть  еще  одно  имя,  связанное  с  этим  файлом);  root  -  имя

владельца,  2048  -  число символов в файле, nov 3 12:11 - дата и

время  создания  или  последней  модификации  файла  (3  ноября в

12-11); bin - имя файла (каталог команд).

     Во второй   строке  указан  обычный  текстовый  файл (boot),

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



     Команда   "pwd"   (без   флагов   и   аргументов)   сообщает

местоположение  пользователя  в  файловой  системе.  С ее помощью

выводится полное имя текущего каталога.

     При  входе в систему пользователь оказывается в определенной

заранее  вершине  дерева.  Пусть,  например,  это  будет  каталог

"/usr".

     Изменить  местонахождение можно командой "cd <каталог>". Так

можно перейти в каталог /usr/include/sys, набрав команду



	cd  /usr/include/sys



здесь указано полное имя , или



	cd  include/sys



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

     Отличительный  признак  относительного  имени  -  отсутствие

символа "/" в начале.

     Команда  "cd  .."  осуществит  переход  вверх  на предыдущий

уровень.    Из    "/usr/include/sys"    произойдет    переход   в

"/usr/include",  а  команда  "cd" (т.е. без параметров) осущствит

переход  в  начальный директорий пользователя (т.е. директорий, в

котором пользователь оказывается при входе в систему).



     Создать новые каталоги можно с помощью команды



     mkdir <имена создаваемых каталогов>



     Так  команда  "mkdir  err new" создаст в данном каталоге два

новых каталога с относительными именами "err" и "new".

     Удалить  пустой  (не  содержащий  файлов)  каталог  можно  с

помощью команды



     rmdir <имена удаляемых каталогов>



     Удалить обычный файл можно командой



     rm <имена удаляемых файлов>



     Наиболее   естественный  для  пользователя  способ  создания

файлов   -   это  использование  текстового  редактора  "ed"  или

экранного  редактора  "red" (а также стандартных "vi" и "ех", или

многочисленных прочих "фирменных").

     В  ОС  Unix  около  200  базовых  команд  - инструментальных

средств, позволяющих пользователю решать многие свои проблемы, не

прибегая  к  программированию на языках типа Си или использованию

специальных пакетов.



     Командой



     rm файл-1



можно удалить "файл-1".



    Командой



    rmdir файл-1



     можно  удалить  "файл-1", если это директорий, причем пустой

(т.е. не содержит файлов).



     Командой



     mv старое-имя новое-имя



можно переназвать файл.



     Командой



     cp старое-имя новое-имя



можно скопировать файл (сохранив также старый).



     Очень важна команда



     chmod 755 расчет



     которая   превращает   файл   "расчет",   подготовленный   в

редакторе,  в  командный,  иначе  "расчет"  при попытке вызова не

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

представлений  восьмеричных чисел и триадам прав доступа к файлам

(rwx  -  чтение,  запись,  выполнение).  То  есть определяет, что

создатель расчета может не только выполнить или распечатать текст

этого  расчета,  но  и  вносить в него изменения (7:111 - rwx). А

члены   группы   и  прочие  пользователи  могу  только  читать  и

выполнять, но не могут изменять этот расчет (55:101101 - r-xr-x).





		  3. ПРОСТЕЙШИЕ СРЕДСТВА SHELL



     Командный  язык  shell  (в  переводе  -  раковина, скорлупа)

фактически  есть  язык программирования очень высокого уровня. На

этом  языке  пользователь  осуществляет  управление  компьютером.

Обычно,  после  входа  в систему вы начинаете взаимодействовать с

командной оболочкой (если угодно - она начинает взаимодействовать

с  вами).  Признаком  того,  что оболочка (shell) готова к приему

команд  служит  выдаваемый  ею  на  экран  промптер. В простейшем

случае это один доллар ("$").

     Shell  не  является  необходимым  и  единственным  командным

языком  (хотя  именно  он  стандартизован  в  рамках POSIX [POSIX

1003.2]   -   стандарта   мобильных  систем).  Например,  немалой

популярностью  пользуется язык cshell, есть также kshell, bashell

(из  наиболее популярных в последнее время) и другие. Более того,

каждый  пользователь  может  создать  свой  командный язык. Может

одновременно  на одном экземпляре операционной системы работать с

разными командными языками.

     ОБРАТИТЕ  ВНИМАНИЕ.  shell - это одна из многих команд UNIX.

То  есть  в набор команд оболочки (интерпретатора) "shell" входит

команда  "sh"  -  вызов  интерпретатора  "shell".  Первый "shell"

вызывается  автоматически  при  вашем входе в систему и выдает на

экран промтер. После этого вы можете вызывать на выполнение любые

команды,  в  том  числе  и снова сам "shell", который вам создаст

новую оболочку внутри прежней.

     Так например, если вы подготовите в редакторе файл "f1":



     echo Hello!



     то  это  будет  обычный  текстовый  файл, содержащий команду

"echo", которая при выполнении выдает все написанное правее ее на

экран.  Можно  сделать  файл  "f1"  выполняемым с помощью команды

"chmod  755  f1". Но его можно ВЫПОЛНИТЬ, вызвав явно команду (!)

"sh" ("shell"):



     sh f1



или



     sh < f1



     Файл  можно  выполнить  и  в текущем экземпляре "shell". Для

этого существует специфическая команда "." (точка), т.е.



     . f1



     ВАЖНОЕ   ПРЕДУПРЕЖДЕНИЕ.  Не  начинайте  командные  файлы  с

символа  "#", хотя естественно начинать его с комментария. Дело в

том,  что  такой  командный файл в оболочке C-Shell ("csh") будет

интерпретирован  как  выполняемый  в  "csh",  в  результате будет

активизирован. интерпретатор "csh".

     СОВЕТ.  Начинайте  командный  sh-файл  с  пустой  строки или

пустого оператора ":".

     Поскольку  UNIX  -  система многопользовательская, вы можете

даже  на персональном компьютере работать параллельно, скажем, на

12-ти  экранах  (переход  с  экрана  на  экран ALT/функциональная

клавиша),  имея  на  каждом  экране нового (или одного и того же)

пользователя со своей командной оболочкой. Можете и в графическом

режиме X-Window также открыть большое число окон, а в каждом окне

может быть свой свой пользователь со своей командной оболочкой...

     Стержневым элементом языка shell является команда.





		  3.1. Структура команд



     Команды в shell обычно имеют следующий формат:



     <имя команды> <флаги> <аргумент(ы)>



     Например:



     ls  -ls  /usr/bin



     где ls - имя команды выдачи содержимого директория,

     -ls  - флаги ( "-" - признак флагов, l - длинный формат, s -

об'ем файлов в блоках).

     /usr/bin -  директорий, для которого выполняется команда.

     Эта  команда  выдаст  на  экран в длинном формате содержимое

директория  /usr/bin,  при  этом  добавит  информацию  о  размере

каждого файла в блоках.

     К сожалению, такая структура команды выдерживается далеко не

всегда.  Не  всегда перед флагами ставится минус, не всегда флаги

идут   одним   словом.   Есть   разнообразие  и  в  представлении

аргументов.   К   числу  команд,  имеющих  экзотические  форматы,

относятся  и такие "ходовые" команды, как сс, tar, dd, find и ряд

других.

     Как    правило  (но   не   всегда),   первое   слово   (т.е.

последовательность  символов  до  пробела,  табуляции  или  конца

строки)  shell воспринимает,  как  команду.  Поэтому  в командной

строке



     cat cat



     первое   слово   будет   расшифровано  shell,   как  команда

(конкатенации),  которая   выдаст  на  экран  файл с именем "cat"

(второе слово), находящийся в текущем директории.





		   3.2. Группировка команд.



Средства группировки:

     ;   и   <перевод   строки>   -  определяют  последовательное

выполнение команд;

     & - асинхронное (фоновое) выполнение предшествующей команды;

     &&  - выполнение последующей команды при условии нормального

завершения предыдущей, иначе игнорировать;

     ||   -   выполнение  последующей  команды  при  ненормальном

завершении предыдущей, иначе игнорировать.



     При  выполнении  команды в асинхронном режиме (после команды

стоит   один   амперсенд)  на  экран  выводится  номер  процесса,

соответствующий  выполняемой  команде,  и  система, запустив этот

фоновый процесс, вновь выходит на диалог с пользователем.

     Например,  наберем  (экзотическую)  команду "find" в фоновом

режиме  для  поиска  в  системе  ,  начиная от корня "/", файла с

именем  "conf",  а  затем  "pwd" в обычном режиме. На экране этот

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



--------------------------------

| $ find / -name conf -print & | ввод команды "find"

|                              |

| 288                          | номер (PID) фонового процесса

|                              |

| $ pwd                        | ввод команды "pwd"

|                              |

| /mnt/lab/asu                 | результат работы "pwd"

|                              |

| $                            | возвращение shell в промптер

|                              |

| /usr/include/sys/conf        | результат работы "find"

|                              |

--------------------------------



     Иногда  необходимо,  чтобы все фоновые процессы завершились,

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

специальная  команда  "wait  [PID]".  Эта команда ждет завершения

указанного   идентификатором  (числом)  фонового  процесса.  Если

команда  без  параметра,  то  она  ждет  завершения  всех фоновых

процессов, дочерних для данного "sh".



     Для  группировки  команд также могут использоваться фигурные

"{}"  и  круглые  "()"  скобки.  Рассмотрим  примеры,  сочетающие

различные способы группировки:



     Если введена командная строка



     k1 && k2; k3



     где  k1, k2 и k3 - какие-то команды, то "k2" будет выполнена

только  при  успешном  завершении  "k1";  после любого из исходов

обработки  "k2" (т.е. "k2" будет выполнена, либо пропущена) будет

выполнена "k3".



     k1 && {k2; k3}



     Здесь  обе  команды ("k2" и "k3") будут выполнены только при

успешном завершении "k1".



     {k1; k2} &



     В фоновом режиме будет выполняться последовательность команд

"k1" и "k2".



     Фоновые   процессы   (как   и   теневую   экономику)  сложно

уничтожить,  поскольку  традиционная  команда  "CTL/C"  прерывает

только   процессы   переднего  плана.  Для  уничтожения  фонового

процесса  надо  знать его номер. При запуске фонового процесса на

экран  выдается  число,  соответствующее  номеру (идентификатору)

этого  процесса  (PID). Если этот номер забыт или надо убедиться,

что этот процесс не закончен, с помощью команды



	ps -aux



     можно  получить  перечень  идентификаторов  процессов (PID),

имена  пользователей,  текущее  время,  затраченное процессами, и

т.д.

     В   выведенной   таблице   можно   найти  номера  процессов,

подлежащих   уничтожению,  например  это  "849"  и  "866".  Тогда

командой



	kill -9  866 849



     можно  уничтожить  эти  процессы.  При уничтожении процессов

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

уничтожаемым   процессам   (или   иметь   имя  привилегированного

пользователя).



     ПРЕДУПРЕЖДЕНИЕ.    Если   параллельно   обрабатывается   или

создается  файл с ОДНИМ именем (например, несколько пользователей

вызвали  в  редактор  один и тот же файл), то в системе продолжит

существование  тот  вариант  файла, который возвращен (записан) в

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

компьютеров,   которые   редактируют   один  файл  параллельно  с

нескольких экранов.



     Круглые  скобки  "()", кроме выполнения функции группировки,

выполняют  и  функцию  вызова  нового  экземпляра  интерпретатора

shell.

     Пусть мы находились в начальном каталоге "/mnt/lab/asu"

     Тогда в последовательности команд



     cd ..; ls; ls



     две  команды  "ls" выдадут 2 экземпляра содержимого каталога

"/mnt/lab", а последовательность

     (cd ..; ls) ls

     выдаст  сначала  содержимое  каталога  "/mnt/lab",  а  затем

содержимое  "/mnt/lab/asu",  т.к.  при  входе в скобки вызывается

новый   экземпляр  shell,  в  рамках  которого  и  осуществляется

переход. При выходе из круглых скобок происходит возврат в старый

shell и в старый каталог.





		   3.3. Перенаправление команд



     Стандартный ввод (вход) - "stdin" в ОС UNIX осуществляется с

клавиатуры  терминала,  а  стандартный  вывод  (выход) - "stdout"

направлен  на  экран терминала. Существует еще и стандартный файл

диагностических  сообщений  - "stderr", о котором речь будет чуть

позже.

     Команда,  которая  может  работать  со  стандартным входом и

выходом, называется ФИЛЬТРОМ.

     Пользователь  имеет удобные средства перенаправления ввода и

вывода   на   другие  файлы  (устройства).  Символы  ">"  и  ">>"

обозначают перенаправление вывода.



	ls >f1



     команда  "ls"  сформирует  список файлов текущего каталога и

поместит его в файл "f1" (вместо выдачи на экран). Если файл "f1"

до этого существовал, то он будет затерт новым.



     pwd >>f1



     команда  pwd  сформирует  полное  имя  текущего  каталога  и

поместит его в конец файла "f1", т.е. ">>" добавляет в файл, если

он непустой.

     Символы "<" и "<<" обозначают перенаправление ввода.



     wc -l <f4   и   wc -l >f4  f2



     Данный  конвейер  из  файла "f1" ("cat") выберет все строки,

содержащие   слово   "result"   ("grep"),   отсортирует  ("sort")

полученные  строки,  а  затем  пронумерует  ("cat  -b") и выведет

результат в файл "f2".

     Поскольку  устройства  в  ОС  UNIX представлены специальными

файлами,  их можно использовать при перенаправлениях. Специальные

файлы  находятся  в  каталоге  "/dev".  Например,  "lp" - печать;

"console"  -  консоль; "ttyi" - i-ый терминал; "null" - фиктивный

(пустой) файл (устройство).

     Тогда,  например,



     ls > /dev/lp



     выведет  содержимое  текущего каталога на печать, а



     f1 < /dev/null  обнулит  файл "f1".



     sort f1 | tee /dev/lp | tail -20



     В  этом  случае  будет  отсортирован  файл "f1" и передан на

печать, а 20 последних строк также будут выданы на экран.



     Вернемся  к  перенаправлению выхода. Стандартные файлы имеют

номера:  0  -  stdin,  1  -  stdout  и  2  -  stderr. Если вам не

желательно  иметь  на  экране  сообщение  об  ошибке,  вы  можете

перенаправить  его  с  экрана  в  указанный вами файл (или вообще

"выбросить",   перенаправив   в   файл   "пустого  устройства"  -

/dev/null). Например при выполнении команды



     cat f1 f2



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

файлов "f1" и "f2", выдаст вам, например, следующее



    111111 222222



    cat: f2: No such file or directory



где 111111 222222 - содержимое файла "f1", а файл "f2" отсутствует,

о чем команда "cat" выдала сообщение в стандартный файл диагностики,

по умолчанию, как и стандартный выход, представленный экраном.

     Если  вам не желательно такое сообщение на экране, его можно

перенаправить в указанный вами файл:



     cat f1 f2 2>f-err



     сообщения  об  ошибках  будут  направляться (об этом говорит

перенаправление  "2>")  в  файл  "f-err".  Кстати,  вы можете всю

информацию  направлять  в  один  файл  "ff", использовав в данном

случае конструкцию



     cat f1 f2 >>ff 2>ff



     Можно   указать   не  только  какой  из  стандартных  файлов

перенаправлять,   но  и  в  какой  стандартный  файл  осуществить

перенаправление.



     cat f1 f2 2>>ff 1>&2



     Здесь    сначала   "stderr"   перенаправляется   (в   режиме

добавления)    в   файл   "ff",   а   затем   стандартный   выход

перенаправляется  на  "stderr",  которым к этому моменту является

файл "ff". То есть результат будет аналогичен предыдущему.

     Конструкция "1>&2" - означает, что кроме номера стандартного

файла,  в который перенаправить,  необходимо впереди ставить "&";

вся конструкция пишется без пробелов.

     <&-   - закрывает стандартный ввод.

     >&-   - закрывает стандартный вывод.





	  3.4. Генерация имен файлов.



     При генерации имен используют метасимволы:

     *   -   произвольная  (возможно  пустая)  последовательность

символов;

     ? - один произвольный символ;

     [...] - любой из символов, указанных в скобках перечислением

и/или с указанием диапазона;



     cat f* - выдаст все файлы каталога, начинающиеся с "f";

     cat *f* - выдаст все файлы, содержащие "f";

     cat   program.?   -   выдаст   файлы   данного   каталога  с

однобуквенными расширениями, скажем "program.c" и "program.o", но

не выдаст "program.com";

     cat  [a-d]*  -  выдаст файлы, которые начинаются с "a", "b",

"c", "d". Аналогичный эффект дадут и команды "cat [abcd]*" и

"cat [bdac]*".





		  3.5. Командные файлы.



     Для  того,  чтобы текстовый файл можно было использовать как

команду, существует несколько возможностей.

     Пусть  с  помощью  редактора  создан  файл  с  именем "cmd",

содержащий одну строку следующего вида:



     date; pwd; ls



     Можно  вызвать  shell  как команду (!), обозначаемую "sh", и

передать  ей  файл "cmd",  как  аргумент или как перенаправленный

вход, т.е.



      $  sh cmd    или     $ sh . Введенное вами число

воспринимается   им   не  как  число,  а  как  последовательность

символов(!).  Интерпретор  не  проверяет, что вы ввели. Поэтому в

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

абракадабра  или  просто  нажатие  ,  как  значение пустой

строки.  (Для обеспечения проверки формата ввода следует написать

свою команду).



     При  обращении  к  shell-переменной  необходимо перед именем

ставить символ "$". Так команды



     echo $var_2

     echo var_2



выдадут на экран



     ОС UNIX

     var_2



     И еще один пример. Фрагмент командного файла:



     echo "var_2 = $var_2"



выдаст на экран



     var_2 = ОС UNIX



     В  команде  "echo" первое использование "var_2" - это просто

текст,   а  второе  ("$var_2")  -  это  значение  соответствующей

переменной.

     То  что здесь присутствуют пробелы между именем переменной и

символом  присваивания,  а  также  между  символом присваивания и

значением,  так  это  потому,  что  здесь  мы  имеем  дело лишь с

текстом,   куда   подставлены   значения   переменных.  Там,  где

действительно  выполняется  присваивание,  пробелы  в этих местах

НЕДОПУСТИМЫ.   Присваивание,  скажем,  w=  означает  присваивание

переменной   "w"   пустой   строки.  Но  и  пустую  строку  лучше

присваивать аккуратно, например w="".



     Для  того,  чтобы  имя  переменной  не сливалось со строкой,

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

     Пусть  a=/mnt/lab/asu/



тогда



     cat /mnt/lab/asu/prim



и



     cat ${a}prim



     равноценны  (т.е.  "cat" выдаст на экран содержимое одного и

того же файла).

     Если  также  предположить,  что  в  системе  есть переменная

"prim" и "prim=dir" , то команда



     echo ${a}$prim



выдаст на экран



     /mnt/lab/asu/dir





		  4.2. Экранирование



     Рассмотрим более подробно приемы экранирования, используемые

в  shell.  В  качестве средств экранирования используются двойные

кавычки (" "), одинарные кавычки (' ') и бэк-слэш (\).

     Из примеров очевидно их действие:

     Можно  в  одной  строке  записывать  несколько приcваиваний.



     x=22 y=33 z=$x

     A="$x" B='$x' C=\$x

     D="$x + $y + $z"  E='$x + $y + $z'  F=$x\ +\ $y\ +\ $z



     (присваивание G=$x + $y не было бы выполнено из-за пробелов)



     Тогда



     echo A = $A   B = $B   C = $C

     echo D = $D   E = $E   F = $F

     eval echo evaluated A = $A

     eval echo evaluated B = $B

     eval echo evaluated C = $C



     Выдадут на экран



     A = 22 B = $x C = $x

     D = 22 + 33 + 22 E = $x + $y + $z F = 22 + 33 + 22

     evaluated A = 22

     evaluated B = 22

     evaluated C = 22



     ВНИМАНИЕ. В трех последних случаях использована своеобразная

команда   "eval"   (от   evaluate   -   означивать),   которая  в

подставленной  в  нее  (в качестве  аргумента) команде  выполняет

означивание  переменных  (если  таковые  имеются).  В  результате

значение "A" остается прежним, поскольку "A" имеет значение "22".

А  переменные "B" и "C" имеют значение "$x". За счет означивания,

которое было выполнено командой "eval" - evaluated "B" и "C" дают

значения "22".

     Еще один пример на "eval".

     Пусть



     w=\$v v=\$u u=5



     В результате выполнения команд



	       echo $w

	  eval echo $w

     eval eval echo $w



     на экран будет выведено



     $v

     $u

     5



     Приведем  еще  примеры,  связанные с экранированием перевода

строки.  Пусть  переменной  "string" присвоено значение "массива"

2x3:



abc

def



     Обатим  внимание,  что  для  избежания  присваивания  лишних

пробелов  вторая строка массива начата с первой позиции следующей

строки:



string="abc

def"



Тогда три варианта записи переменной в команде "echo"



echo  $string

echo '$string'

echo "$string"



дадут соответсвенно три различных результата:



abc def



$string



abc

def



а последовательность команд



echo "строка первая

строка вторая" > f1



echo 'строка первая

строка вторая' > f2



cat f1 f2



даст выдаст последовательно одинаковые файлы f1 и f2:



строка первая

строка вторая

строка первая

строка вторая



     Заметим   также,  что  бэк-слэш  (\)  не  только  экранирует

следующий  за  ним символ, что позволяет использовать специальные

символы  просто  как  символы, представляющие сами себя (он может

экранировать  и  сам  себя  -  \\), но в командном файле бэк-слэш

позволяет об'единять строки в одну (экранировать конец строки).

    Например, приводившийся ранее пример командной строки:



     cat f1 | grep -h result | sort | cat -b > f2



может быть записан в командном файле, скажем, как



     cat f1 | grep -h  \

     result | sort | cat -b > f2



     Кстати,  эффект  продолжения командной строки обеспечивает и

символ   конвейера.   В   данном  случае  это  может  дать  более

симпатичный результат, например:



     cat f1         |

     grep -h result |

     sort           |

     cat -b > f2





	       4.3. Манипуляции с shell-переменными



     Несмотря   на   то,  что  shell-переменные  в  общем  случае

воспринимаются  как  строки, т.е "35" - это не число, а строка из

двух   символов   "3"   и   "5",   в   раде   случаев  они  могут

интерпретироваться иначе, например, как целые числа.

     Разнообразные     возможности    имеет    команда    "expr".

     Проиллюстрируем некоторые на примерах:

     Выполнение командного файла:



     x=7 y=2

     a=`expr $x + $y`   ; echo a=$a

     a=`expr $a + 1`    ; echo a=$a

     b=`expr $y - $x`   ; echo b=$b

     c=`expr $x '*' $y` ; echo c=$c

     d=`expr $x / $y`   ; echo d=$d

     e=`expr $x % $y`   ; echo e=$e



выдаст на экран



     a=9

     a=10

     b=-5

     c=14

     d=3

     e=1



     ВНИМАНИЕ.  Операция  умножения ("*") обязательно должна быть

заэкранирована, поскольку в shell этот значек воспринимается, как

спецсимвол,  означающий,  что на это место может быть подставлена

любая последовательность символов.

     Следует  обратить  также  внимание  на обязательные пробелы,

отделяющие переменные и знаки операций.



     С   командой   "expr"  возможны  не  только  (целочисленные)

арифметические операции, но и строковые:



     A=`expr 'cocktail' : 'cock'`  ; echo $A

     B=`expr 'cocktail' : 'tail'`  ; echo $B

     C=`expr 'cocktail' : 'cook'`  ; echo $C

     D=`expr 'cock' : 'cocktail'`  ; echo $D



     На   экран   будут   выведены   числа,   показывающее  число

совпадающих  символов  в цепочках (от начала). Вторая из строк не

может быть длиннее первой :



     4

     0

     0

     0



     И наконец, об условной замене переменныйх.

     Если переменные, скажем "х", "y", "z", не определены, то при

обращении к переменным

     ${x-new} - в качестве значения "x" будет выдано "new",

     ${y=new} - в качестве значения "у" будет присвоено "new",

     ${z?new} - в качестве значения "z" будет выдано "z: new" и

соответствующая процедура прекращается.

     Во  всех  этих случаях, если переменная была к этому времени

определена, то ее значение используется обычным образом.

     А  в  следующем  случае наоборот, пусть переменная "v" имеет

какое-то значение, тогда

     ${z+new}  -  в  качестве  значения "z" будет выдано "new", а

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





		    4.4. Экспорт переменных



     В  ОС  UNIX  существует  понятие процесса. Процесс возникает

тогда,   когда   запускается  на  выполнение  какая-либо  команда

(расчет).

     Например,  при  наборе на клавиатуре "р " порождается

процесс  расчета  "р".  В  свою очередь "р" может породить другие

процессы. Допустим, что "р" вызывает расчеты "р1" и "р2", которые

последовательно порождают соответсвующие процессы.

     У каждого процесса есть своя среда - множество доступных ему

переменных.  Например,  до  запуска  расчета "р" уже существовала

среда,  в  которой  уже  были  определены некоторые переменные (о

стандартных  переменных  речь пойдет несколько позже). Запуск "р"

порождает  новую  среду; уже в ней будут порождены расчеты "р1" и

"р2".

     Переменные   локальны  в  рамках  процесса,  в  котором  они

объявлены,  т.е.  где  им присвоены значения (описание переменных

отсутсвует  -  они  все  одного  типа).  Для того, чтобы они были

доступны  и  другим порождаемым процессам, надо передать их явным

образом. Для этого используется встроенная команда "export".



     Пример.

     Пусть расчет (командный файл) "p", имеющий вид:



     # расчет p

     echo Расчет p

     varX=0 varY=1

     echo varX=$varX varY=$varY

     export varY

     p1  # вызов расчета p1

     p2  # вызов расчета p2

     echo Снова расчет p: varX=$varX varY=$varY



     вызывает командные файлы "p1" и "p2", имеющие вид:



     # расчет p1

     echo Расчет p1

     echo varX=$varX varY=$varY

     varX=a varY=b

     echo varX=$varX varY=$varY

     export varX



     # расчет p2

     echo Расчет p2

     echo varX=$varX varY=$varY

     varX=A varY=B

     echo varX=$varX varY=$varY

     export varY



     На экран будут выданы следующая информация:



     Расчет p

     varX=0 varY=1

     Расчет p1

     varX= varY=1

     varX=a varY=b

     Расчет p2

     varX= varY=1

     varX=A varY=B

     Снова расчет p: varX=0 varY=1



     Из  примера  видно,  что  значения переменных экспортируются

только  в  вызываемые расчеты (и не передаются "вверх" и "вбок").

Экспортировать переменные можно и командой "set" с флагом "-a".

     НА   ВСЯКИЙ   СЛУЧАЙ   заметим,  что  на  передачу  значений

переменных    никакого    влияния   не   оказывает   "физическое"

взаимное расположение (файлов) расчетов в файловой системе.





		4.5. Параметры



     В  командный  файл  могут  быть  переданы параметры. В shell

используются  позиционные параметры (т.е. существенна очередность

их  следования).  В  командном  файле  соответствующие параметрам

переменные  (аналогично  shell-переменным)  начинаются  с символа

"$", а далее следует одна из цифр от 0 до 9:



     Пусть  расчет  "examp-1"  вызывается  с параметрами "cock" и

"tail".  Эти  параметры  попадают  в новую среду под стандартными

именами  "1" и "2". В (стандартной) переменной с именем "0" будет

храниться имя вызванного расчета.

     При  обращении  к  параметрам  перед  цифрой ставится символ

доллара "$" (как и при обращении к переменным):

     $0 - соответствует имени данного командного файла;

     $1 - первый по порядку параметр;

     $2 - второй параметр и т.д.



     Пусть командный файл с именем "examp-1" имеет вид



      echo Это расчет $0:

      sort $2 >> $1

      cat $1



     а файлы "cock" и "tail" содержат соответсвенно



cock:

      Это отсортированный файл:



tail:

      1

      3

      2



     Тогда после вызова команды



      examp-1 cock tail



на экране будет



     Это расчет examp-1:

     Это отсортированный файл:

     1

     2

     3



     Поскольку  число  переменных,  в  которые могут передаваться

параметры,  ограничено  одной  цифрой,  т.е.  9-ю  ("0",  как уже

отмечалось  имеет  особый  смысл), то для передачи большего числа

параметров используется специальная команда "shift".

     Рассмотрим ее действие на примере.



     Пусть командный файл "many" вызывается с 13-ю параметрами



     many 10 20 30 40 50 60 70 80 90 100 110 120 130



     И имеет вид





     ###

     # many: Передача большого числа параметров.

     echo "$0: Много параметров"

     echo " Общее число параметров = $#

     Исходное состояние: $1 $5 $9 "

     shift

     echo "1 сдвиг: первый=$1 пятый=$5 девятый=$9"

     shift 2

     echo "1 + 2 = 3 сдвига: первый=$1 пятый=$5 девятый=$9"

     perem=`expr $1 + $2 + $3`

     echo $perem



     В  результате  первого  применения  команды  "shift"  второй

параметр  расчета  вызывается  как $1, третий параметр вызывается

как  $2,  ...  десятый  параметр, который был исходно недоступен,

вызывается как $9. Но стал недоступным первый параметр!

     После выполнения этого расчета на экране будет:



     many: Много параметров

     Общее число параметров = 13

     Исходное состояние: 10 50 90

     1 сдвиг: первый=20 пятый=60 девятый=100

     1 + 2 = 3 сдвиг: первый=40 пятый=80 девятый=120

     150



     Своеобразный подход к параметрам дает команда "set".

     Например, фрагмент расчета



     set a b с

     echo первый=$1 второй=$2 третий=$3



     выдаст на экран



     первый=a второй=b третий=c



     т.е.  команда  "set"  устанавливает значения параметров. Это

бывает  очень  удобно.  Например,  команда "date" выдает на экран

текущую  дату,  скажем, "Mon May 01 12:15:10 2000",  сосотящую из

пяти слов, тогда



      set `date`

      echo $1 $3 $5



      выдаст на экран



      Mon 01 2000



     Команда   "set"   позволяет   также   осуществлять  контроль

выполнения программы, например:

     set -v - на терминал выводятся строки, читаемые shell.

     set +v - отменяет предыдущий режим.

     set -x - на терминал выводятся команды перед выполнением.

     set +x - отменяет предыдущий режим.

     Команда  "set"  без параметров выводит на терминал состояние

программной среды (см далее).



	       4.6. Подстановки shell-интерпретатора



     Перед  началом  непосредственной интерпретации и выполнением

команд,   содержащихся   в   командных  файлах,  shell  выполняет

различные виды подстановок:

     1.   ПОДСТАНОВКА   РЕЗУЛЬТАТОВ.   Выполняются  все  команды,

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

результат.

     2.  ПОДСТАНОВКА  ЗНАЧЕНИЙ  ПАРАМЕТРОВ  И ПЕРЕМЕННЫХ. То есть

слова, начинающиеся на "$", заменяются соответсвующими значениями

переменных и параметров.

     3.    ИНТЕРПРЕТАЦИЯ   ПРОБЕЛОВ.   Заэкранированные   пробелы

игнорируются.

     4. ГЕНЕРАЦИЯ ИМЕН ФАЙЛОВ. Проверяются слова на наличие в них

спецсимволов   ("*", "?","[]")   и  выполняются    соответсвующие

генерации.





		  4.7. Программная среда



     Каждый  процесс имеет среду, в которой он выполняется. shell

использует ряд переменных этой среды.

     Если  вы  наберете команду "set" без параметров, то на экран

будет  выдана информация о ряде стандартных переменных, созданных

при  входе  в  систему  (и  передаваемых  далее  всем вашим новым

процессам  "по  наследству"),  а  также  переменных,  созданных и

экспортируемых вашими процессами.

     Конкретный  вид и содержание выдаваемой информации в немалой

степени зависит от того, какая версия UNIX используется и как

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

     Вот лишь часть того, что выдала мне команда "set":



     HOME=/home/sae

     PATH=/usr/local/bin:/usr/bin:/bin:.:/usr/bin/X11:

     IFS=



     LOGNAME=sae

     MAIL=/var/spool/mail/sae

     PWD=/home/sae/STUDY/SHELL

     PS1=${PWD}:" "

     PS2=>

     SHELL=/bin/bash

     TERM=linux

     TERMCAP=console|con80x25|dumb|linux:li#25:co#80::

     UID=501

     perem=stroka

     x=5



     Прокомментируем эти присваивания значений переменным.



     HOME=/home/sae  -  это  имя  домашнего директория, в котором

пользователь  (в  данном  случае  я)  оказывается  после  входа в

систему.  То  есть,  правильно  набрав  имя и пароль, я окажусь в

директории "/home/sae".



     PATH=/bin:/usr/bin:.:/usr/local/bin:/usr/bin/X11    -    эта

переменная  задает  последоватьельность  файлов  (ТРОПУ), которые

просматривает "shell" в поисках команды. Имена файлов разделяются

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

очередности  следования  имен  в  тропе.  НО  ПЕРВОНАЧАЛЬНО поиск

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

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

например   "echo",  "cd",  "pwd",  "date".  После  этого  система

просматривает   директорий  "/bin",  в  котром  могут  находиться

команды "sh", "cp", "mv", "ls" и т.п. Затем директорий "/usr/bin"

с  командами  "cat",  "сс",  "expr",  "nroff",  "man"  и  многими

другими.  Далее  поиск  происходит в текущем директории (".", или

другое обозначение - "пусто", т.е.""), где скорее всего находятся

написанные вами команды (расчеты).

     После  набора  командной  строки  и  нажатия  "shell"

(после   выполнения   необходимых  подстановок)  распознает  имя,

соответстующее  команде  и  осуществляеет ее поиск в директориях,

перечисленных   в   тропе.   Если   команда  размещена  вне  этих

директориев  -  она не будет найдена. Если присутствует несколько

команд   с  одинаковым  именем,  то  вызвана  будет  та,  которая

расположена в директории, просматриваемом первым.

     Тропу, как и прочие перемнные, можно легко менять, добавляя,

переставляя  или  исключая  директории.  (Кстати,  представленная

тропа получена из "настоящей" путем сокращений и перестановок).



     IFS=   - (Внутренний Разделитель Полей) перечисляет символы,

которые  служат  для  разделения  слов (полей). Таковыми являются

"пробел",  "табуляция" и "перевод строки", поэтому здесь слева от

присваивания ничего не видно и занято две строки.



     LOGNAME=sae  - имя входа ("имя" пользователя).



     MAIL=/var/spool/mail/sae  -  имя  файла, в который поступает

(электронная) почта.



     PWD=/home/sae/STUDY/SHELL  - имя текущего директория



     PS1=${PWD}:" "   - вид промтера. В данном случае в промптере

будет  выдаваться  имя текущего директория двоеточие и пробел. То

есть здесь будет "/home/sae/STUDY/SHELL: ".



     PS2=>   -   этот   промтер   (эдесь  ">")  используется  как

приглашение    к   продолжению   ввода   (в   очередной   строке)

незаконченной  команды. Например, наберите открывающую скобку "("

и  после  нажатия    в  следующей  строке  вы увидите этот

промптер.  Если  пока  не  знаете,  что  дальше  делать, наберите

закрывающую скобку ")" - и он исчезнет.



     SHELL=/bin/bash - эта переменная указывает оболочку, которую

использует   пользователь.   В   данном  случае  используется  не

(стандартный)  shell  ("sh"),  а  "продвинутая"  версия - "bash",

написанная тем же автором (Bourne-Again SHell).



     TERM=linux - указание типа терминала.



     TERMCAP=console|con80x25|dumb|linux:li#25:co#80::          -

(TERMinal  CAPacity) это (очень сильно) обрезанная строка задания

параметров терминала.



     UID=501       -  идентификатор пользователя (мой - "501").



     perem=stroka

     x=5          - переменные, которые ввел пользователь.



     Исходная  среда  устанавливается  автоматически  при входе в

систему с использованием файлов типа "/etc/rc" и "/etc/.profile".

     ВАЖНОЕ  ЗАМЕЧАНИЕ.  Один  из  способов  просто изменит среду

(например,  тропу поиска команд, вид промтера, вид оболочки, цвет

экрана  и  т.п.) можно, разместив эту информацию в своем домашнем

директории     в     специальизированном     файле     ".profile"

(${HOME}/.profile), присвоив нужные значения переменным среды. То

есть  вызвать  это  файл  в  редактор и написать, что пожелаете).

Тогда   при   каждом  вашем  входе  в  систему  этот  файл  будет

автоматически  выполняться и устанавливать новую среду. Этот файл

должен   ОБЯЗАТЕЛЬНО  размещаться  в  вашем  ДОМАШНЕМ  директории

(директории входа).

     Если  вы внесли изменения в ".profile", то для переноса этих

изменений в среду необходимо выполнить этот файл. Для этого можно

выйти   и   заново  войти  в  систему,  а  можно  воспользоваться

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

из системы, т.е.



     . .profile



     Следует  иметь  в  виду,  что  имена  файлов, начинающиеся с

точки,  вообще имеют особый статус. Так, они не выдаются на экран

простой  командой "ls" - необходимо вызывать эту команду с флагом

"-a". Кстати, и не уничтожаются огульно командой "rm *".



     Дописать  новый  совй  директорий "my" в тропу команд можно,

записав в ".profile", например



     PATH=${PATH}:/home/sae/my



или



     PATH=${PATH}:${HOME}/my



     Как   правило,   устанавливаемые  переменные  среды  следует

экспортировать. Например,



     export TERM PATH REDKEYS MAIL



     Кроме  определения  переменных  в ".profile" можно выполнить

команды, например команда

      stty -lcase

установит терминал в режим "большие и маленькие буквы"; а команда

      cat заставка

     выдаст  на  экран  заставку  , которую вы сами подготовите в

файле  "заставка"  с  учетом  ваших  эстетических  пристрастий  и

художественных способностей.





     Сам  интерпретатор  shell автоматически присваивает значения

следующим переменным (параметрам):

     ?  - значение, возвращенное последней командой;

     $  - номер процесса;

     !  - номер фонового процесса;

     #  - число позиционных параметров, передаваемых в shell;

     *  - перечень параметров, как одна строка;

     @  - перечень параметров, как совокупность слов;

     -  - флаги, передаваемые в shell.

     При  обращении к этим переменным (т.е при использовании их в

командном файле - shell-программе) следует впереди ставить "$".

     Пример. Вызов расчета



     specific par1 par2 par3



     имеющего вид



     ###

     # specific: Специальные параметры (переменные)



     echo $0 - имя расчета

     echo $? - код завершения

     echo $$ - идентификатор последнего процесса

     echo $! - идентификатор последнего фонового процесса

     echo

     echo $* - значения параметров, как строки

     echo $@ - значения параметров, как слов

     echo

     set -au

     echo $- - режимы работы интерпретатора



     Выдаст на экран



     specific - имя расчета

     0 - код завершения

     499 - идентификатор последнего процесса

     98 - идентификатор последнего фонового процесса



     par1 par2 par3 - значения параметров, как строки

     par1 par2 par3 - значения параметров, как слов



     au - режимы работы интерпретатора





     Код  "0" соответсвует нормальному завершению процесса.

     Важную   роль   при   создании   уникальных   файлов  играет

специальная   переменная  "$$",  значение  которой  соответствует

номеру процесса, выполняющего данный расчет. Каждый новый расчет,

выполняемый компьютером, инициирует один или несколько процессов,

автоматически  получающих  номера  по-порядку. Поэтому, используя

номер  процесса в качестве имени файла, можно быть уверенным, что

каждый  новый  файл  будет иметь новое имя (не запишется на место

уже  существующего).  Достоинство  является и главным недостатком

такого  способа  именования файлов. Неизвестно, какие имена будут

присвоены  файлам.  И, если в рамках данного процесса можно найти

файл "не глядя", т.е., обратившись к нему, используя $$, то потом

такие  файлы  можно  легко  потерять.  Это создает дополнительные

проблемы при отладке программ.

     "echo" без параметров выводит пустую строку.

     Различия  $*  и $@ состоит в том, что певая переменная может

быть  представлена  как



     "par1  par2  par3"



а вторая как



     "par1" "par2" "par3"



     Пример, иллюстрирующий различия "$*" и "$@" будет рассмотрен

в связи с оператором "for".

     Для   иллюстрации   мы   установили  командой  "set"  режимы

интерпретатора  ("a" - все последующие переменные экспортируются;

"u"  -  отсутствие параметра считать ошибкой), что и отразилось в

специальной переменной "$-".





		  5. ПРОГРАММНЫЕ  СТРУКТУРЫ



     Как во всяком языке программирования в тексте на языке shell

могут  быть  комментарии. Для этого используется символ "#". Все,

что  находится  в строке (в командном файле) левее этого символа,

воспринимается интерпретатором как комментарий. Например,



     # Это комментарий.

     ## И это.

     ### И это тоже.



     Как  во  всяком  процедурном  языке программирования в языке

shell   есть   операторы.   Ряд  операторов  позволяет  управлять

последовательностью  выполнения  команд. В таких операторах часто

необходима  проверка  условия,  которая  и определяет направление

продолжения вычислений.





		 5.1. Команда test ("[ ]")



     Команда  test  проверяет  выполнение  некоторого  условия. С

использованием  этой  (встроенной)  команды формируются операторы

выбора и цикла языка shell.



     Два возможных формата команды:



     test условие

или

     [ условие ]



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

чтобы писать перед условием слово "test", будем заключать условие

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

     На  самом  деле  shell  будет  распознавать  эту  команду по

открывающей  скобке  "[",  как  слову(!), соответсвующему команде

"test".    Уже    этого    достаточно,   чтобы   предупредить   о

распространенной ошибке начинающих: Между скобками и содержащимся

в них условием обязательно должны быть пробелы.

     Пробелы  должны быть и между значениями и символом сравнения

или  операции  (как,  кстати,  и  в  команде "expr"). Не путать с

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

     В shell используются условия различных "типов".



     УСЛОВИЯ ПРОВЕРКИ ФАЙЛОВ:

     -f file - файл "file" является обычным файлом;

     -d file - файл "file" - каталог;

     -с file - файл "file" - специальный файл;

     -r file - имеется разрешение на чтение файла "file";

     -w file - имеется разрешение на запись в файл "file";

     -s file - файл "file" не пустой.



     Примеры. Вводя с клавиатуры командные строки в первом случае

получим  подтверждение  (код  завершения  "0"),  а  во  втором  -

опровержение (код завершения "1"). "specific" - имя существующего

файла.



     [ -f specific ] ; echo $?

     0



     [ -d specific ] ; echo $?

     1



     УСЛОВИЯ ПРОВЕРКИ СТРОК:

     str1 = str2  - строки "str1" и "str2" совпадают;

     str1 != str2  - строки "str1" и "str2" не совпадают;

     -n str1  - строка "str1" существует (непустая);

     -z str1  строка "str1" не существует (пустая).



     Примеры.



     x="who is who"; export x; [ "who is who" = "$x" ]; echo $?

     0



     x=abc ; export x ; [ abc = "$x" ] ; echo $?

     0



     x=abc ; export x ; [ -n "$x" ] ; echo $?

     0



     x="" ; export x ; [ -n "$x" ] ; echo $?

     1



     ВАЖНОЕ  ЗАМЕЧАНИЕ.  Команда  "test"  дает  значение "истина"

(т.е.  код завершения "0") и просто если в скобках стоит непустое

слово.



      [ privet ] ; echo $?

      0



      [ ] ; echo $?

      1



     Кроме  того,  существуют  два  стандартных значения условия,

которые  могут  использоваться вместо условия (для этого не нужны

скобки).



      true ; echo $?

      0



      false ; echo $?

      1



     УСЛОВИЯ СРАВНЕНИЯ ЦЕЛЫХ ЧИСЕЛ:

     x -eq y   - "x" равно "y",

     x -ne y   - "x" неравно "y",

     x -gt y   - "x" больше "y",

     x -ge y   - "x" больше или равно "y",

     x -lt y   - "x" меньше "y",

     x -le y   - "x" меньше или равно "y".



     То  есть  в данном случае команда "test" воспринимает строки

символов  как  целые (!) числа. Поэтому во всех остальных случаях

"нулевому"  значению  соответствует  пустая  строка.  В данном же

случае,  если  надо  обнулить  переменную,  скажем,  "x",  то это

достигается присваиванием "x=0".

     Примеры.



     x=abc ; export x ; [ abc -eq "$x" ] ; echo $?

     "[": integer expression expected before -eq



     x=321 ; export x ; [ 321 -eq "$x" ] ; echo $?

     0



     x=3.21 ; export x ; [ 3.21 -eq "$x" ] ; echo $?

     "[": integer expression expected before -eq



     x=321 ; export x ; [ 123 -lt "$x" ] ; echo $?

     0



     СЛОЖНЫЕ УСЛОВИЯ:

     Реализуются с помощью типовых логических операций:

     !   -  (not)  инвертирует значение кода завершения.

     -o  -  (or) соответсвует логическому "ИЛИ".

     -a  -  (and) соответсвует логическому "И".

     ПРЕДУПРЕЖДЕНИЕ. Не забывайте о пробелах.



     Примеры.



      [ ! privet ] ; echo $?

      1



     x=privet; export x; [ "$x" -a -f specific ] ; echo $?

     0



     x="";export x; [ "$x" -a -f specific ] ; echo $?

     1



     x="";export x; [ "$x" -a -f specific -o privet ] ; echo $?

     0



     x="";export x; [ "$x" -a -f specific -o ! privet ] ; echo $?

     1



     СОВЕТ. Не злоупотреблять сложными условиями.





		5.2. Условный оператор "if"



    В общем случае оператор "if" имеет структуру



    if  условие

      then  список

	 [elif  условие

	  then  список]

      [else  список]

    fi



     Здесь  "elif"  сокращенный  вариант  от "else if" может быть

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

произвольного  числа  операторов  "if" (как и других опреаторов).

Разумеется  "список"  в  каждом  случае должен быть осмысленный и

допустимый в данном контексте.

     Конструкции



     [elif  условие

      then  список]

и

     [else  список]



     не  являются  обязательными (в данном случае для указания на

необязательность  конструкций использованы квадратные скобки - не

путать с квадратными скобками команды "test"!).

     Самая усеченная структура этого оператора



    if   условие

      then  список

    fi



     если  выполнено  условие  (как  правило  это ком получен код

завершения "0", то выполняется "список", иначе он пропускается.

     Обратите  внимание,  что  структура  обязательно завершается

служебным  словом  "fi".  Число  "fi", естественно, всегда должно

соответсвовать числу "if".



     Примеры.

     Пусть написан расчет "if-1"



     if [ $1 -gt $2 ]

	then pwd

	else echo $0 : Hello!

     fi



     Тогда вызов расчета



     if-1 12 11



даст



     /home/sae/STUDY/SHELL



а

     if-1 12 13



даст



     if-1 : Hello!



     Возможно  использовать  в  условии  то  свойство  shell, что

команды  могут  выдавать различный код завершения. Это напоминает

приемы программирования на Си. Пусть расчет "if-2" будет



     if a=`expr "$1" : "$2"`

	then echo then a=$a code=$?

	else echo else a=$a code=$?

     fi



тогда вызов



     if-2  by by



даст



     then a=2 code=0



а



     if-2  by be



даст



     else a=0 code=1





     Еще пример на вложенность



     ###

     # if-3: Оценка достижений



     echo -n " А какую оценку получил на экзамене?: "

     read z

     if [ $z = 5 ]

	then echo  Молодец !

	elif [ $z = 4 ]

	     then echo  Все равно молодец !

	     elif [ $z = 3 ]

		  then echo  Все равно !

		  elif [ $z = 2 ]

		       then echo  Все !

		       else echo   !

     fi



     Можно  обратить  внимание на то, что желательно использовать

сдвиги  при  записи  программ,  чтобы  лучше выделить вложенность

структур.





	       5.3. Оператор выбова ("case")



     Оператор выбора "case" имеет структуру:



     case   строка  in

	шаблон)  список команд;;

	шаблон)  список команд;;

	    ...

     esac



     Здесь  "case" "in" и "esac" - служебные слова. "Строка" (это

может  быть  и  один  символ)  сравнивается  с  "шаблоном". Затем

выполняется  "список  команд" выбранной строки. Непривычным будет

служебное   слово   "esac",  но  оно  необходимо  для  завершения

структуры.

     Пример.



     ###

     # case-1: Структура "case".

     #         Уже рассматривавшийся в связи со

     #         структурой "if" пример проще и

     #         нагляднее можно реализовать с

     #         помощью структуры "case".



     echo -n " А какую оценку получил на экзамене?: "

     read z

     case $z in

	5) echo Молодец !            ;;

	4) echo Все равно молодец !  ;;

	3) echo Все равно !          ;;

	2) echo Все !                ;;

	*) echo  !                   ;;

     esac



     Непривычно  выглядят  в конце строк выбора ";;", но написать

здесь  ";"  было  бы  ошибкой. Для каждой альтернативы может быть

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

одну  строку,  то символ ";" будет использоваться как разделитель

команд.

     Обычно  последняя  строка  выбора  имеет  шаблон  "*", что в

структуре   "case"   означает   "любое   значение".   Эта  строка

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

(здесь  $z) ни с одним из ранее записанных шаблонов, ограниченных

скобкой ")". Значения просматриваются в порядке записи.



     ###

     # case-2:  Справочник.

     #          Для различных фирм по имени выдается

     #          название холдинга, в который она входит



     case $1 in

	     ONE|TWO|THREE) echo Холдинг: ZERO    ;;

		   MMM|WWW) echo Холдинг: Not-Net ;;

	 Hi|Hello|Howdoing) echo Холдинг: Привет! ;;

			 *) echo Нет такой фирмы  ;;

     esac



     При вызове "case-2 Hello" на экран будет выведено:



     Холдинг: Привет!



     А при вызове "case-2 HELLO" на экран будет выведено:



     Нет такой фирмы



     Коль  скоро слово "case" переводится как "выбор", то это как

бы  намек  на  то,  что  можно  эту  структуру  использовать  для

реализации простейших меню.



     ###

     # case-3: Реализация меню с помощью команды "case"



     echo "Назовите файл, а затем (через пробел)

     наберите цифру, соответствующую требуемой

     обработке:

	    1 - отсортировать

	    2 - выдать на экран

	    3 - определить число строк  "

     read x y  # x - имя файла, y - что сделать

     case $y in

	1) sort   < $x               ;;

	2) cat    < $x               ;;

	3) wc -l  < $x               ;;

	*) echo "

		   Мы не знаем

		   такой команды ! " ;;

     esac



     Разумеется,  желания  могут  быть  более  сложные и на месте

отдельных  команд могут быть последовательности команд или вызовы

более сложных расчетов.

     Напишем  команду  "case-4",  которая  добавляет информацию к

файлу,  указанного  первым  параметром  (если  параметр один), со

стандартного  входа, либо (если 2 параметра) из файла, указанного

в качестве первого параметра:



     ###

     # case-4: Добавление в файл.

     #         Использование стандартной переменной.

     # "$#" -  число параметров при вводе расчета

     # ">>" -  перенаправление с добавлением в файл



     case $# in

	  1) cat >> $1                           ;;

	  2) cat >> $2 < $1                      ;;

	  *) echo "Формат: case-4 [откуда] куда" ;;

     esac



     "$1"  (при  "$#=1")  -  это  имя файла, в который происходит

добавление со стандартного входа.

     "$1"  и  "$2"  (при  $#=2)  - это имена файлов , из которого

("$1") и в который ("$2") добавлять.

     Во  всех  других случаях (*) выдается сообщение о том, каким

должен быть правильный формат команды.





	  5.4. Оператор цикла с перечислением ("for")



    Оператор цикла "for" имеет структуру:



    for имя [in список значений]

	do

	    список команд

	done



     где  "for"  - служебное слово определяющее тип цикла, "do" и

"done" - служебные слова, выделяюшие тело цикла. Не забывайте про

"done"! Фрагмент "in список значений" может отсутствовать.



     Пусть команда "lsort" представлена командным файлом



     for i in f1 f2 f3

     do

       proc-sort $i

     done



     В  этом примере имя "i" играет роль параметра цикла. Это имя

можно рассматривать как shell-переменную, которой последовательно

присваиваются   перечисленные  значения  (i=f1,  i=f2,  i=f3),  и

выполняется в цикле команда "procsort".

     Часто  используется форма "for i in *", означающая "для всех

файлов текущего каталога".

     Пусть  "proc-sort"  в свою  очередь представляется командным

файлом



   cat $1 | sort | tee /dev/lp > ${1}_sorted



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

сортировки выводятся на печать ("/dev/lp") и направляются в файлы



   f1_sorted  f2_sorted  и  f3_sorted



     Можно  сделать  более универсальной команду "lsort", если не

фиксировать  перечень файлов в команде, а передавать произвольное

их число параметрами.

     Тогда головная программа будет следующей:



   for i

       do

	 proc-sort $i

       done



     Здесь   отсутствие   после   "i"  служебного  слова  "in"  с

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

параметры  команды. Результат предыдущего примера можно получить,

набрав



   lsort f1 f2 f3



     Усложним   ранее   рассматривавшуюся   задачу   (под  именем

"case-2")  определения  холдинга  фирмы.  Теперь можно при вызове

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

структуре   оператора   "for"  фрагмента  "in  список  значений",

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



     ###

     # holding: Справочник.

     #          Для различных фирм по имени выдается

     #          название холдинга, в который она входит

     for i

	 do

	     case $i in

			 ONE|TWO|THREE) echo Холдинг: ZERO    ;;

			       MMM|WWW) echo Холдинг: Not-Net ;;

		     Hi|Hello|Howdoing) echo Холдинг: Привет! ;;

				     *) echo Нет такой фирмы  ;;

	     esac

	 done





     При вызове "holding Hello HELLO ONE" на экране будет:



     Холдинг: Привет!

     Нет такой фирмы

     Холдинг: Not-Net



     Еще пример.



     ###

     # subdir: Выдает имена всех поддиректориев

     #         директория с именем $dir



	     for i in $dir/*

	     do

		if [ -d  $i ]

		   then echo $i

		fi

	     done



     Следующий  расчет  иллюстрирует  полезный,  хотя  и  с долей

трюкачества,  способ повторения одних и тех же действий несколько

раз. Переменныя "i" принимает здесь пять значений: 1, 2, 3, 4, 5,

но  внутри цикла эта переменная отсутствует и поэтому ее значение

никакой  роли  не  играет и ни чего не меняет. С таким же успехом

переменная  "i"  могла принимать значения, скажем ф о к у с , а в

результате  точно  также  было бы пять раз повторено одно и то же

вычисление содержимого цикла без изменений.



     ###

     # print-5: Организации пятикратного выполнения команды



     for i in 1 2 3 4 5

	do

	   cat file-22 > /dev/lp

	done



     Расчет  "print-n" иллюстрирует еще одну полезную возможность

в   использовании   цикла   "for".  Здесь,  после  "for  i  ...",

отсутствуют  "in ..." и перечень имен, т.е. перечнем имен для "i"

становится   перечень   параметров,  а  следовательно  количество

печатаемых экземпляров можно менять.



     ###

     # print-n: Задание числа копий

     #          через параметры



     for i

	  do

		  cat file-22 > /dev/lp

	  done



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



	for i in $*



     поскольку значение "$*" - есть список значений параметров.



     Отметим  различие  в  специальных  переменных  "$*"  и "$@",

представляющих    перечень    параметров.   Первый   представляет

параметры, как строку, а второй, как совокупность слов.

     Пусть командный файл "cmp" имеет вид:



     for i in "$*"

       do

	   echo $i

       done

     echo

     for i in "$@"

	do

	   echo $i

	done



При вызове



     cmp aa bb cc



на экран будет выведено



     aa bb cc



     aa

     bb

     cc





	5.4. Оператор цикла с истинным условием ("while")



     Структура "while", также обеспечивающая выполнение расчетов,

предпочтительнее  тогда,  когда  неизвестен заранее точный список

значений  параметров  или  этот  список  должен  быть  получен  в

результате вычислений в цикле.



    Оператор цикла "while" имеет структуру:



    while условие

	do

	    список команд

	done



     где  "while"  -  служебное  слово  определяющее  тип цикла с

истинным  условием.  Список  команд  в  теле  цикла (между "do" и

"done")  повторяется  до  тех  пор,  пока  сохраняется истинность

условия (т.е. код завершения последней команды в теле цикла равен

"0")  или  цикл  не  будет прерван изнутри специальными командами

("break", "continue" или "exit"). При первом входе в цикл условие

должно выполняться.



     ###

     # print-50: Структура "while"

     #           Расчет позволяет напечатать 50

     #           экземпляров файла "file-22"

     n=0

     while [ $n -lt 50 ]    # пока n < 50

     do

	n=`expr $n + 1`

	cat file-22 > /dev/lp

     done



     Обратим   внимание   на   то,  что  переменной  "n"  вначале

присваивается  значение  0,  а  не пустая строка, так как команда

"expr"  работает  с  shell-переменными как с целыми числами, а не

как со строками.



     n=`expr $n + 1`



     т.е. при каждом выполнении значение "n" увеличивается на 1.



     Как  и  вообще  в  жизни,  можно  реализовать  то же самое и

сложнее.  Расчет  "рr-br"  приведен  для иллюстрации бесконечного

цикла  и  использования  команды  "break",  которая  обеспечивает

прекращение цикла.



     ###

     # рr-br: Структура "while" c "break"

     #        Расчет позволяет напечатать 50

     #        экземпляров файла "file-22"

     n=0

     while true

     do

	if [ $n -lt 50 ]           # если n < 50

	   then n=`expr $n + 1`

	   else break

	fi

	     cat file-22 > /dev/lp

     done



     Команда  "break  [n]"  позволяет выходить из цикла. Если "n"

отсутствует,  то  это эквивалентно "break 1". "n" указывает число

вложенных  циклов,  из  которых надо выйти, например, "break 3" -

выход из трех вложенных циклов.

     В  отличие  от  команды  "break" команда "continue [n]" лишь

прекращает  выполнение  текущего  цикла  и  возвращает  на НАЧАЛО

цикла.  Она также может быть с параметром. Например, "continue 2"

означает  выход  на  начало  второго  (если  считать  из глубины)

вложенного цикла.

     Команда  "exit  [n]"  позволяет  выйти вообще из процедуры с

кодом  возврата  "0"  или  "n"  (если  параметр  "n" указан). Эта

команда  может использоваться не только в циклах. Даже в линейной

последовательности  команд  она  может  быть полезна при отладке,

чтобы прекратит выполнение (текущего) расчета в заданной точке.





	   5.5. Оператор цикла с ложным условием ("until")



    Оператор цикла "until" имеет структуру:



    until условие

	do

	    список команд

	done



     где  "until"  -  служебное  слово  определяющее  тип цикла с

ложным условием. Список команд в теле цикла (между "do" и "done")

повторяется  до  тех  пор,  пока сохраняется ложность условия или

цикл  не  будет  прерван изнутри специальными командами ("break",

"continue" или "exit"). При первом входе в цикл условие не должно

выполняться.

     Отличие  от  оператора  "while"  состоит  в том, что условие

цикла  проверяется  на  ложность  (на  ненулевой  код  завершения

последней  команды  тела  цикла) проверяется ПОСЛЕ каждого (в том

числе и первого!) выполнения команд тела цикла.

     Программистов,  знакомых  с  операторами  "until"  в  других

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

     Примеры.



     until false

     do

	 read x

	 if   [ $x = 5 ]

	   then echo enough ; break

	   else echo some more

	 fi

     done



     Здесь   программа  с  бесконечным  циклом  ждет  ввода  слов

(повторяя  на  экране  фразу  "some more"), пока не будет введено

"5".  После  этого выдается "enough" и команда "break" перкращает

выполнение цикла.

     Другой  пример  ("Ожидание полдня") иллюстрирует возможность

использовать в условии вычисления.



     until date | grep 12:00:

     do

	 sleep 30

     done



     Здесь каждые 30 секунд выполняется командная строка условия.

Команда  "date"  выдает  текущую  дату  и  время.  Команда "grep"

получает  эту  информацию  через  конвейер  и пытается совместить

заданный  шаблон "12:00:" с временем, выдаваемым командой "date".

При несовпадении "grep" выдает код возврата "1", что соответсвует

значению "ложь", и цикл "выполняет ожидание" в течение 30 секунд,

после  чего повторяется выполнение условия. В полдень (возможно с

несколькими   секундами)  произойдет  сравнение,  условие  станет

истинным,  "grep"  выдаст на экран соответсвующую строку и работа

цикла закончится.





		  5.6. Пустой оператор



     Пустой оператор имеет формат



     :



     Ничего не делает. Возвращает значение "0".

Например, в конструкции "while :" или ставить в начале командного

файла,   чтобы   гарантировать,  что  файл  не  будет  принят  за

выполняемый файл для "csh".





		  5.7. Функции в shell



     Функция   позволяет  подготовить  список  команд  shell  для

последующего выполнения.



     Описание функции меет вид:



     имя()

     {

     список команд

     }



     после  чего  обращение  к  функции  происходит по имени. При

выполнении  функции не создается нового процесса. Она выполняется

в среде соответсвующего процесса. Аргументы функции становятся ее

позиционными  параметрами;  имя  функции  -  ее нулевой параметр.

Прервать  выполнение  функции  можно оператором "return [n]", где

(необязательное) "n" - код возврата.

     Пример.   Вызов   на  выполнение  файла  "fun"



     echo $$



     fn()                 # описание функции

     {

     echo xx=$xx

     echo $#

     echo $0: $$ $1 $2

     xx=yy ; echo xx=$xx

     return 5

     }



     xx=xx ; echo xx=$xx

     fn a b               # вызов функции "fn" с параметрами

     echo $?

     echo xx=$xx



содержащего описание и вызов функции "fn", выдаст на экран:



     749

     xx=xx

     xx=xx

     2

     fun: 749 a b

     xx=yy

     5

     xx=yy





		5.8. Обработка прерываний ("trap")



     Бывает   необходимо   защитить   выполнение   программы   от

прерывания.

     Наиболее   часто   приходится   встречаться   со  следующими

прерываниями, соответсвующими сигналам:

     0  - выход из интерпретатора,

     1  - отбой (отключение удаленного абонента),

     2  - прерывание от <Del>,

     9  - уничтожение (не перехватывается),

     15 - окончание выполнения.



     Для  защиты от прерываний существует команда "trap", имеющая

формат:



     trap 'список команд' сигналы



     Если в системе возникнут прерывания, чьи сигналы перечислены

через  пробел  в  "сигналы",  то  будет выполнен "список команд",

после  чего  (если  в  списке  команд  не  была выполнена команда

"exit")  управление  вернется  в  точку  прерывания и продолжится

выполнение командного файла.



     Например,  если перед прекращением по прерываниям выполнения

какого  то командного файла необходимо удалить файлы в "/tmp", то

это может быть выполнено командой "trap":



    tarp 'rm /tmp/* ; exit 1' 1 2 15



     которая  предществует  прочим  командам  файла. Здесь, после

удаления  файлов  будет  осуществлен  выход  "exit" из командного

файла.

     Команда  "trap"  позволяет и просто игнорировать прерывания,

если  "список  команд"  пустой.  Так например, если команда "cmd"

выполняется  очень  долго,  а  пользователь  решил отключиться от

системы,   то  для  продолжения  выполнения  этой  команды  можно

написать, запустив команду в фоновом режиме:



     ( trap '' 1; cmd )&





			    * * *



     Программирование на shell здесь описано достаточно полно, но

далеко  не  исчерпывающе  :-) Поэтому знакомство с литературой не

только  желательно, но и необходимо. Тем более, что описание даже

стандартных   команд   (в   силу  очень  больших  об'емов)  здесь

отсутствует.

     Список  литературы  содержит  некоторые из (быстро растущего

перечня) книг на русском языке.

     При  подготовке  материалов  по  программированию  на  shell

прежде всего использованы книги [ 9, 1, 10, 11 ].





		       6. ЛИТЕРАТУРА



1.   Кристиан К. Введение в операционную систему UNIX. -

  М.: Финансы и статистика, 1985. -318 с.

2.   Готье Р. Руководство по операционной системе UNIX.

  -М.: Финансы и статистика, 1985. -232 с.

3.   Браун П. Введение в операционную систему UNIX.

  -М.: Мир, 1987. -287 с.

4.   Томас Р., Йейтс Дж.Операционная система UNIX. Руководство

  для пользователей. -М.: Радио и связь, 1986. -352 с.

5.   Банахан М., Раттер Э. Введение в операционную систему UNIX.

  -М.: Радио и связь, 1986. -341 с.

6.   Тихомиров В.П., Давидов М.И. Операционная система UNIX:

  Инструментальные средства программирования. -М.: Финансы и

  статистика, 1988. -206 с.

7.   Баурн С. Операционная система UNIX. -М.: Мир, 1986. -462 с.

8.   Беляков М.И. и др. Инструментальная мобильная операционная

  система ИНМОС. -М.: Финансы и статистика, 1985 -231 с.

9.   Топхем Д., Чьюнг Х.В. Юникс и Ксеникс. -М.: Мир, 1988.

  -392 с.

10.  Беляков М.И., Рабовер Ю.И., Фридман А.Л. Мобильная операци-

  онная система. -М.: Радио и связь, 1991 -208 с.

11.  Керниган Б.В., Пайк Р. UNIX - Универсальная  среда програм-

  мирования. -М.: Финансы и статистика, 1992 -304 с.




Источник: http://www.linuxrsp.ru/docs/shell.html

Поиск файла по содержимому этого файла

[announce]То что давно хотел узнать :)[/announce]

Вот так можно найти строку по содержимому файла.

$ find /etc -type f -exec grep -Hn "nameserver" {} \; 2>/dev/null

Вот так можно найти все файлы в каталоге /etc в которых есть слово «nameserver»
Опции grep:

H — выводим имя файла со строкой.
n — номер строки в файле.

Ошибки перенаправляем в /dev/null
При желании можно написать вот такой скрипт:

#/bin/sh

dir='.';
if [ -z $1 ] 
then
	echo 'Команду нужно запускать вот так: find.str  [dir]';
else
	if [ -z $2 ]
	then
		dir=$2
	fi
	
	find . -type f -exec grep -Hn $1 {} \; 2>/dev/null
fi

Вообще вот ссылка полезная — http://www.openspin.org/materials/courses/admin/ch04s02.html

 

Unix — пример работы с текстом

Скачал тут недавно книгу из двух текстовых файлов в koi8-r и с переводами строки в стиле Win (^M)

Решил поправить это дело таким вот образом:

$ cat book_p1.txt book_p2.txt | sed 's/\r//' | iconv -f koi8-r -t utf8 > book.txt

Вот так вот :) Unix — это круто!

Немного о правах в Unix

[announce]Чтобы было понятно и не забыть самому, что значат циферки в правах :)[/announce]
Итак, основы Unix, но я всегда  забываю как формируются цифры прав доступа в Unix, поэтому и решил написать сюда об этом. чтобы в случае  чего можно было подглядеть.

Вот примерная схема:

-r-w-x—r-w-x—r-w-x-
——-   ——-  ———
    U         G         O

Легенда:
U — Владелец файла
G — Группа владельца файла
O — Все остальные

-r- — Разрешение на чтение
-w- -Разрешение на запись
-x- -Разрешение на использование

Теперь о том как формируются цифры:

Каждое разрешение представляет из себя ,если грубо, булевое значение т.е может быть равно 0 (выключено) или  1(включено)
Таким образом получаем двоичный код   -111-111-111- что значит -rwx-rwx-rwx, а как мы знаем  из курса информатики 111 в двоичной системе счисления есть 7 в восьмеричной, значит запись -111-111-111- в двоичной системе счисления будет равна -7-7-7- в восьмеричной. Кажется все логично и просто :)

Нембольшая таблица, чтобы было понятно наглядно.

Доступ Двоичное число Восьмеричное число
000 0
—x 001 1
-w- 010 2
-wx 011 3
r— 100 4
r-x 101 5
rw- 110 6
rwx 111 7

Вот небольшая программка, которую я написал на js. Может кому-нибудь она поможет лучше понять принцип прав доступа в Unix

При написании статьи пользовался книгой — Маслякова В.Г, Linux на 100%(+DVD), СПб.:Питер,2009, 336c.

настройка sudo

[announce]Настраиваем sudo в ARCHLinux..[/announce]
Программа sudo предназначина для запуска команд с привелегиями root пользователя:
например:

$ sudo halt

Для настройки рекомендуеться запустить команду visudo от ползователя root, которая запустит редактор vi с файлом для редактирования — /etc/sudoers

Немного о синтаксисе файла.

Чтобы разрешить пользователю выполнять все команды от root  нужно ввести строку:

  

user ALL=(ALL) ALL

Если нужно дать возможность запускать на машине только несклько команд, то можно искользовать такой синтаксис:

user ALL=/usr/sbin/halt

Эта строка позволит запускать пользователю user команду halt. Для того,  чтобы позволить пользователю запускать несколько  команд от  пользователя root нужно перечислить команды, включая абсолютный путь к команде, через запятую.

user      ALL=/usr/sbin/halt,  /bin/mount

Эта строка позволит запускать от полззователя root команды halt и mount

Итак, примерно получается такой синтаксис как я понял:

первое поле user — имя пользователя от которого будет запускаться команда sudo
второе поле ALL= — это имя машины на которой разрашено запускать каоманды через sudo
третье поле (ALL) — это пользователь от кого будет запущена команда через sudo, по-умолчанию root
четвертое поле — список команд с абсолютным путем к команде.

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

Defaults insults 

Данная строка укажет на то что sudo будет хранить пароль 10мин.

Defaults:ALL timestamp_timeout=10

*Примечание: каждая запись занимает одну строку, поэтому некоторые записи могут быть большими, для переноса можно ипользовать символ \ тобишь как-то так:

user      ALL=/usr/sbin/halt,  \
/bin/mount

Это будет одна строка.

Источники:

$ man sudo
$ man sudoers

http://wiki.archlinux.org/index.php/Sudo_(Русский)
http://wiki.archlinux.org/index.php/Sudo

конечно же :)

Очень странный сайт с какими-то ошибками и неправильной кодировкой (сразу видно НАШ былокодерский! :) ) — http://www.infocity.kiev.ua/os/content/os299_2.phtml 

Поднимаем Samba

[announce]Поднимаем Samba в FreeBSD 8.1[/announce]
Итак, для того, чтобы подружить windows с FreeBSD поднимаем самбу

# cd /usr/ports/net/samba3 && make install clean

Далее добавляем в /etc/rc.conf строку — inetd_enable=»YES»

Запускаем —
# /etc/rc.d/inetd start

Открываем браузер и вводим в адресную строку: <domain_samba_server>:901 где  <domain_samba_server> имя или ip машины на которой запустили самбу, например http://localhost:901 или http://127.0.0.1:901
После ввода пароля и логина можем управлять настройками самбы из браузера.

Проще как мне кажется отредактировать файл /usr/local/etc/smb.conf при помощи любимого текстового редактора ( конечно же vi :) )

После сохранения настроек запускаем Самбу —
/etc/rc.conf — сюда по традиции добавляем строки:

winbindd_enable="YES"
nmbd_enable="YES"
smbd_enable="YES"

И запускаем скрипт запуска самбы:

# /usr/local/etc/rc.d/samba start

 

LAMP для FreeBSD

[announce]Ставим на фрю LAMP ну или тогда уж FAMP ))[/announce]
Нужно поставить Apache+Mysql+php на FreeBSD 8.1, который в народе заветься LAMP я буду назвать FAMP так как в качестве ОС системы буду использовать не Linux а FreeBSD
Вот как делать:

Для начала поставим Apache:*

# cd  /usr/ports/www/apache13 && make install clean

Затем ставим php и mysql

# cd /usr/ports/lang/php5 && make install clean

В меню config выбираем модуль Apache
Ставим mysql

# cd /usr/ports/databases/mysql50-server && make install clean

прописываем в в rc.conf строки для автоматического старта серверов Apache и Mysql:

apache_enable=»YES»
mysql_enable=»YES»

Запускаем:

# /usr/local/etc/rc.d/mysql-server start &
# apachectl start

можно попробовать сделать скрипт типа такого —

# vim install-lamp.sh

#!/bin/sh
cd  /usr/ports/www/apache13 && make install clean
cd /usr/ports/lang/php5 && make install clean
cd /usr/ports/databases/mysql50-server && make install clean
echo ‘apache_enable=»YES»‘ >> /etc/rc.conf
echo ‘mysql_enable=»YES»‘ >> /etc/rc.conf
/usr/local/etc/rc.d/mysql-server start &
apachectl start

Делаем скрипт запускаемым:

# chmod 775 install-lamp.sh

или запускаем так:

# /bin/sh install-lamp.sh

Зупускать нужно из под пользователя root или используя команду sudo

Вот FAMP и готов )))

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

PS. В процессе установки FreeBSD я по нехватки опыта отметил php и apache для установки из коробки, все поставилось хорошо, вот только php установился не как модуль apache, а отдельно о чем мне после запуска сервера apache, сообщил inpdex.php, который отобразился как текст в браузере :) Мне пришлось удалить все пакеты связанные с php через pkg_delete и затем собрать php из портов с поддержкой модуля для Apache.

Источник информации: http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/network-apache.html
Привожу англоязычную документацию не из-за понтов (с английским у меня не очень..) просто дело в том, что в локализованном хэндбуке вариант настройки и установки не подошёл мне (скорее всего из-за устаревшей информации, которая приводится в русскоязычной документации)

**Пока не поменял владельца /var/db/mysql вот так — chown -R mysql:mysql /var/db/mysql/ mysql скрвер не стартавала (решение подглядел вот тут в комментариях — http://chrv.ru/?p=11)

FreeBSD

[announce]Ставлю и кручу фряку (очень увлекательно :) ) Подробности читайте в http://killercoder.ru/zennix/ [/announce]

666666666666666666666666666666666666666666666666626666666666666666666666666666666666666666666666666666666666666666666666
6666666666666666666666666666666666666666666
6624 4666666666666666666666666666666666666666666666666666666666666666666666
66666666666666666666666666666666666666666
62445 466666666666666666666666666666662222666666666666666666666666666666666666
66666666666666666666666666666666666666
6244225 56666666666666666666666666666666666524 42666666666666666666666666666666666
666666666666666666666666666666666666
6244224 4666666666666666666666666666666666666424 466666666666666666666666666666666
6666666666666666666666666666666666
62422224 466666666666666666666666666666666666666425 2666666666666666666666666666666
666666666666666666666666666666666
622222225 56662224455 554226666666666666666422 466666666666666666666666666666
66666666666666666666666666666666
642222224 5 42222455 5426666666666664225 46666666666666666666666666666
66666666666666666666666666666666
222222225555555542225555 526666666624225 2666666666666666666666666666
66666666666666666666666666666666
52222245422244222224222225 566622454222 5666666666666666666666666666
66666666666666666666666666666666
4222254224422252222444442225 5544442222225 666666666666666666666666666
66666666666666666666666666666666
22225424266662522426666254225 55555 5222222222225 5666666666666666666666666666
66666666666666666666666666666666
64254446666665222666666625222244555 542222222455 2666666666666666666666666666
666666666666666666666666666666666
45442666666422266666666625222225 544445 26666666666666666666666666666
666666666666666666666666666666666
4542666666242666666666662 2222245 5266666666666666666666666666666
66666666666666666666666666666666
65426224266422666666666666542222255 526666666666666666666666666666666
66666666666666666666666666666666
2542465 5644 52 5266666666542222254 52666666666666666666666666666666666
66666666666666666666666666666666
5455 5 524 22 66666662522222224 4266666666666666666666666666666666666
666666666666666666666666666666
62525 44 55 26666662522222224 4266666666666666666666666666666666666666
66666666666666666666666666666
2242225 425 26666665422222225 26666666666666666666666666666666666666666
666666666666666666666666666
6242222244444424 56666665522222222 56666666666666666666666666666666666666666
66666666666666666
6666666666242222242222222245 466666655222222224 46666666666666666666666666666666666666666
66666666666666666
6222266666522222242222222245555222244555422224555 26666666666666666666666666666666666666666
666666666666666666
6222222662422222444222224 522222222222222225 466666666666666666666666666666666666666666
6666666666666
666666622422266222222224555555555422222222222222225 5666666666666666666666666666666666666666666
6666666666666
222266662662226624222555222222222222222222222222225 46666666666666666666666666666666666666666666
6666666666666
622224266666222666244445 4222222222222222245 555 266666666666666666666666666666666666666666666
66666666666666
642222222622246666662245 542222222222455 554445 26666666666666666666666666666666666666666666666
6666
622666666666666222222242666666666624 5555555 542222445 52666666666666666666666666666666666666666666666666
66666
62222222666666622222222662222224266622555444422224455 466666666666666666666666666666666666666666666666666
6666666
662222222222222222222252222225 466666625 55555 266666666666666666666666666666666666666666666666666
6666666666
6222222222226666242542224 566666662224444422222222244 266666666666666666666666666666666666666666666666666
6666666666666
666666666666662444445 54222666242222222222222222225 26666666666666666666666666666666666666666666666666
66666666666666666666666666
242222225 422222222222222222225 2666666666666666666666666666666666666666666666666
66666666666666666666666666
422222225 544444444422222224 525 5666666666666666666666666666666666666666666666666
66666666666666666666666666
62244445 522222222245555455 525 266666666666666666666666666666666666666666666666
6666666666666666666666666666
62555444 422222222222455 24 466666666666666666666666666666666666666666666666
666666666666666666666666666666
6224445 4222222222222225 566666666666666666666666666666666666666666666666
666666666666666666666666666666666666
625 54222222222222455 566666666666666666666666666666666666666666666666
66666666666666666666666666666666666666
6 5442222222244 466666666666666666666666666666666666666666666666
666666666666666666666666666666666666666
65 5 5555 5666666666666666666666666666666666666666666666666
666666666666666666666666666666666666666
645 2666666666666666666666666666666666666666666666666
666666666666666666666666666666666666666
222255 5666666666666666666666666666666666666666666666666
666666666666666666666666666666666666666
422222245 522245 266666666666666666666666666666666666666666666666
666666666666666666666666666666666666666
242222222224555 54222445 66666666666666666666666666666666666666666666666
666666666666666666666666666666666666666
6442222222222224 542225 56666666666666666666666666666666666666666666666
66666666666666666666666666666666666666666
25222222222224 55 5266666666666666666666666666666666666666666666
666666666666666666666666666666666666666666
2 5554444455 46666666666666666666666666666666666666666666
666666666666666666666666666666666666666666
2 5 526666666666666666666666666666666666666666
666666666666666666666666666666666666666666
65522245 555 5 5426666666666666666666666666666666666666
6666666666666666666666666666666666666666
662452224455 5444444 55 5 2624 542266666666666666666666666666666666
666666666666666666666666
66666662222222244452224244 5422455 445 26662245 544226666666666666666666666666
66666666666666666
66666666266625 422445444554555555555 56666666622255 5544422266666666666666
66666666666666
66666666666666662 5 542222622224 5442555555 266666666666666222455 554266666666
66666666666666
2666666666666666222666666666666625 422445 6666666666666666666666662222222244555 5466666
66666666666666
2666666666666252666666666666666662 56666666666666666666666666666666666662244 4666
666666666666666
62222666666645266666666622222224 5426666666666666666666666666666252666666666245 466
6666666666666666666
6666666666666666666666666625 542266666666666666666666666666666244445266666624 266
6666666666666666666666666666666
666666622222225 555544222666666666666666666666666666666662244222224 44555 46666
66666666666666666666666666666666666666666
6666666666666666666666666666666666666666666666622442222222225 55426666666
66666666666666666666666666666666666666666666666666666666666666666666666666666666666
6624444444455555 5266666666666666
6666666666666666666666666666666666666666666666666666666666666666666666666666666666
62222222222266666666666666666666666666
666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666

Ставлю и кручу фряку (очень увлекательно :) ) Подробности читайте в http://killercoder.ru/zennix/

ASCII стянул отсюда — http://www.codeismylife.com/ascii_freebsd_daemon/3223.html

Пересборка Мира и ядра

[announce]Пересобрал мир и ядро на только что установленной фряке. Вот как было дело:[/announce]
После установки Фряки мне пришла в голову мысль, что неплохо было бы персобрать мир и ядро системы.
Дальше опишу свои действия и команды, а так же укажу источники информации, которыми я пользовался в процессе.

Итак, приступим

Для оптимизации компиляции нужно отредактировать /etc/make.conf
Пример make.conf можно найти в /usr/share/examples/make.conf
У меня получился вот так — http://killercoder.ru/zennix/Nastroyka_make_conf_v_FreeBSD

Обновляемся через cvsup как тут — http://killercoder.ru/zennix/Obnovlenie_ishodnikov_cherez_cvsup

Читаем тут — http://www.freebsd.org/doc/ru/books/handbook/makeworld.html

Загружаемся в однопользовательский режим:
После загрузки вводим:

# fsck -p
# mount -u /
# mount -a -t ufs
# swapon -a

Переходим в директорию с исходниками (у меня /usr/src/)

# cd /usr/src/

На этапе выбора архитектуры мира произошла накладка, дело в том что uname -a возвратил мне i386, а
dmesg | grep CPU — Athlon64 :)

Нужно было безболезненно перейти на другую архитектуру так как make buildkernel отказался запускаться с параметром в файле конфигурации ядра cpu HAMMER — это для 64х битных атлонов.
Google нашёл по этому поводу статью вот она — http://unixfaq.ru/index.pl?req=qs&id=527

Учитывая данные сведения сделал:

# make buildworld TARGET_ARCH = amd64

Сборка, запустилась. Я не очень силён в команде make, но кажется можно было бы запустить и с параметром -j4, а для amd64 возможно и -j8 для увеличения производительности и скорости сборки.

Дальше переходим 
Копируем ядро GENERIC для нужной нам платформы в удобное место в данном случае это ~/ # cp /usr/src/sys/amd64/conf/GENERIC ~/KERNEL_`date %d_%m_%Y`  Идею с именем нового ядра подсказал lissyara вот отсюда — http://www.lissyara.su/articles/freebsd/tuning/make_kernel/

Редактируем опции ядра при помощи любимого редактора, в моем случае это vi :)

# vi  KERNEL_01_07_2010

Свой конф приводить думаю бессмысленно, могу только сказать, что ознакомится с дополнительными параметрами ядра можно в файле /usr/src/sys/amd64/conf/NOTES и в /usr/src/sys/NOTES — это если вы понимаете по-английски :) я же пользовался опять же Гуглом и http://www.freebsd.org/doc/ru/books/handbook/kernelconfig-config.html,

Собираем ядро
При сборки ядра make buildkernel TARGET_ARCH=amd64 KERNCONF=KERNEL_01_07_2010 выдал ошибку, после перезагрузки компьютера, я повторил попытку, но команда не сработала, тогда я решил пересобрать ядро с командой

# make buildkernel TARGET_ARCH=amd64

Эта команда прошла и запустилась компиляция ядра.
После компиляции запустил установку нового ядра и make выдал ошибку

Error: Please set DESTDIR

Установил DESTDIR:

# export DESTDIR=/usr/src/

Запустил
# make installkernel TARGET_ARCH=amd64

Вроде пошла установка, но выскачела опять ошибка:

cd: can’t cd to /usr/obj/amd64/usr/sys/GENERIC

Обновление исходников через cvsup

[announce]О том как я обновлял исходники фряки через cvsup[/announce]
Ставим cvsup из портов:

# cd /usr/ports/net/cvsup/ && make install clean

Тоже самое без возможности поддержки иксов —
# cd /usr/ports/net/cvsup-without-gui && make install clean

Создаем файл с настройками обновления:
# vi supfile

В файле:

*default release=cvs tag=.tag=RELENG_8                     # Версия системы, которая нам нужна
*default host=cvsup2.ru.FreeBSD.org                            # Хост откуда тянем исходники
*default prefix=/usr                                                        # Куда кладем полученные исходники (этой строкой в /usr/src/)
*default base=/var/db                                                   # Путь к base каталогу для файлов статуса
*default release=cvs delete use-rel-suffix compress     # Дополнительные опции
src-all                                                                             # Забираем все исходники

Запускаем cvsup -g -L 2 supfile

Читаем внимательно:
http://www.freebsd.org/doc/ru/books/handbook/cvsup.html

Настройка make.conf в FreeBSD

[announce]Решил завести себе домашний сервер под FreeBSD. Первое, что решил сделать после установки — оптимизировать опции сборки.[/announce]
Вот мой /etc/make.conf:

CPUTYPE?=athlon64 # Процессор
CFLAGS=-01 -pipe # Флаги сборки
NO_PROFILE=true #Обход построения библиотек для профилирования

# Включать флаги обязательно
NO_CPU_CFLAGS=false
NO_CPU_COPTFLAGS=false

# Отключаем сборку ненужных пакетов
MAKE_KERBEROS4=false
MAKE_KERBEROS5=false
NO_BIND=true
NO_SENDMAIL=true
NO_GAMES=true

# Язык документаций
DOC_LANGS=en_US.ISO8859-1 ru_RU.KOI8-R

Источники информации:
http://www.lissyara.su/articles/freebsd/tuning/make.conf/
http://www.freebsd.org/doc/ru/books/handbook/
/usr/share/examples/etc/make.conf

Интерпретатор командного языка shell

[announce]Пусть будет и тут в помощь быдлокодерам %)[/announce]


Shell - командный язык, могущий выполнять как команды,
введенные с терминала, так и команды, хранящиеся в файле.


Этот текст подготовлен НПО "КЛОТО"

Оглавление

1. Основные понятия языка shell . . . . . . . . . . . . . .
1_1. Ввод-вывод . . . . . . . . . . . . . . . . . . . . . .
1_2. Синхронное и асинхронное выполнение команд . . . . . .
1_3. Конвейер . . . . . . . . . . . . . . . . . . . . . . .
1_4. Метасимволы, генерация имен файлов . . . . . . . . . .

2_ Синтаксис языка shell . . . . . . . . . . . . . . . . .
2_1. Комментарии . . . . . . . . . . . . . . . . . . . . .
2_2. Подстановка результатов выполнения команд . . . . . .
2_3. Переменные и подстановка их значений . . . . . . . . .
2_4. Специальные переменные . . . . . . . . . . . . . . . .

3_ Управляющие конструкции . . . . . . . . . . . . . . . .
3_1. Цикл ДЛЯ . . . . . . . . . . . . . . . . . . . . . . .
3_2. Оператор выбора . . . . . . . . . . . . . . . . . . .
3_3. Условный оператор . . . . . . . . . . . . . . . . . .
3_4. Цикл ПОКА . . . . . . . . . . . . . . . . . . . . . .
3_5. Функции . . . . . . . . . . . . . . . . . . . . . . .
3_6. Зарезервированные слова . . . . . . . . . . . . . . .
3_7. Специальные команды . . . . . . . . . . . . . . . . .

4_ Выполнение shell-программ . . . . . . . . . . . . . . .
4_1. Запуск shellа . . . . . . . . . . . . . . . . . . . .
4_2. Выполнение . . . . . . . . . . . . . . . . . . . . . .
4_3. Окружение . . . . . . . . . . . . . . . . . . . . . .
4_4. Сигналы . . . . . . . . . . . . . . . . . . . . . . .
4_5. Замечания . . . . . . . . . . . . . . . . . . . . . .

5_ Дополнительные сведения . . . . . . . . . . . . . . . .
5_1. Команда test . . . . . . . . . . . . . . . . . . . . .
5_2. Команда expr . . . . . . . . . . . . . . . . . . . . .
5_3. Команда ena . . . . . . . . . . . . . . . . . . . . .

    * 1. Основные понятия языка shell *



    1_1. Ввод-вывод



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

< <имя файла>

служит для переназначения стандартного ввода (дескриптор файла
0),

> <имя файла>

для стандартного вывода (дескриптор файла 1);

<< <строка>

ввод происходит со стандартного ввода, пока не встретится ука-
занная <строка> или конец файла,

>> <имя файла>

для стандартного вывода; если файл существует, то выводимая ин-
формация добавляется к конец этого файла,

<& <цифра>

в качестве стандартного ввода объявляется файл, ассоциированный
с дескриптором <цифра>; аналогично для стандартного вывода

>& <цифра>

<&- и >&-

закрывают соответственно стандартный ввод и вывод.
Если любой из этих конструкций предшествует цифра, то с
указанным файлом будет ассоциирован дескриптор, равный указан-
ной цифре, вместо 0 и 1 по умолчанию. Например,

2 > <имя файла>

для стандартного протокола используется дескриптор 2, а

2 >& 1

ассоциирует дескриптор 2 с файлом, ассоциированным с дескрипто-
ром 1.

... 2>protocol
переназначает стандартный протокол (дескриптор 2) в файл по
имени protocol.

Чтобы переназначить стандартный протокол туда же, куда уже наз-
начен стандартный вывод, следует употребить конструкцию
Ў... 2>&1

Важен порядок переназначения: shell производит переназна-
чение слева направо по указанному списку. Так,

1 > xxx 2 >& 1

сначала ассоциирует дескриптор 1 с файлом xxx, а затем дескрип-
тор 2 с 1, т.е. тоже с xxx. А

2 >& 1 1 > xxx

ассоциирует дескриптор 2 с терминалом, а 1 - с файлом xxx.

Можно переназначить системный ввод на текущий файл:

isql - - <

1_2. Синхронное и асинхронное выполнение команд



Обычно shell ждет завершения выполнения команды. Однако
имеется возможность запустить задачу в асинхронном режиме, т.е.
без ожидания ее завершения. Для этого после команды (после всех
ее аргументов и указаний о переназначении ввода-вывода) надо
поставить знак &. При этом по умолчанию стандартный ввод коман-
ды назначается на пустой файл /dev/null.

Пример: создать файл primer можно по команде

echo > primer

Еще пример: запустить программу prog в асинхронном режиме, что-
бы не надо было дожидаться его завершения, засечь время выпол-
нения, результаты программы направить в файл prog.res, данные о
времени выполнения - в файл prog.tim.

time prog > prog.res 2> prog.tim &

    1_3. Конвейер



Конвейер - последовательность команд, разделенных знаком |.
Если после конвейера стоит ; shell ждет его завершения. Если &
- то не ждет. Роль ; может играть конец строки. Смысл конвейера
в том, что стандартный вывод одной команды замыкается на стан-
дартный ввод другой. Пример конвейера - подсчитать число объ-
ектных файлов в текущем каталоге.

ls *.o | wc -l

    1_4. Метасимволы, генерация имен файлов



Метасимволы - символы, имеющие специальное значение для
интерпретатора :

? * ; & ( ) | ^ < > <пробел> <табуляция> <возврат_каретки>

Однако каждый из этих символов может представлять самого себя,
если перед ним стоит \. Все символы, заключенные между кавычка-
ми ' и ', представляют самих себя. Между двойными кавычками (")
выполняются подстановки команд (см п. 2.2) и параметров (см. п.
2.3), а символы \, `," и $ могут экранироваться предшествующим
символом \.
После всех подстановок в каждом слове команды ищутся сим-
волы *,?, и [. Если находится хотя бы один из них, то это слово
рассматривается как шаблон имен файлов и заменяется именами
файлов, удовлетворяющих данному шаблону (в алфавитном порядке).
Если ни одно имя файла не удовлетворяет шаблону, то он остается
неизменным. Значения указанных символов:
* любая строка, включая и пустую
? один любой символ
[...] любой из указанных между ними символов. Пара
символов, разделенных знаком -, означает любой
символ, который находится между ними, включая и
их самих. Если первым символом после "[" идет
"!", то указанные символы не должны входить в
имя файла

    * 2_ Синтаксис языка shell *



    2_1. Комментарии


Строки, начинающиеся с #, трактуются как комментарии.

    2_2. Подстановка результатов выполнения команд



Выражения можно заключать в обратные кавычки (`). Такие
выражения вычисляются в месте использования. Они могут быть,
например, частью строк. Пример. Пусть параметром макрокоманды
является имя файла с расширением .for. Требуется удалить однои-
менный файл с расширением .err.

name=`ena -n $1`
rm -f ${name}.err

Значение, полученное в результате выполнения команды

ena -n $1

присваивается переменной name. Фигурные скобки использованы для
выделения аргумента операции перехода от имени к значению. Без
них .err приклеилась бы к имени.

    2_3. Переменные и подстановка их значений



Все переменные в языке shell - текстовые. Их имена должны
начинаться с буквы и состоять из латинских букв, цифр и знака
подчеркивания (_). Чтобы воспользоватся значением переменной,
надо перед ней поставить символ $. Использование значения пере-
менной называется подстановкой.
Различается два класса переменных: позиционные и с именем.
Позиционные переменные - это аргументы командных файлов, их
именами служат цифры: $0 - имя команды, $1 - первый аргумент и
т.д. Значения позиционным переменным могут быть присвоены и ко-
мандой set (см. Специальные команды). Пример. После вызова
программы на shellе, хранящейся в файле ficofl:

ficofl -d / \*.for

значением $0 будет ficofl, $1 - -d, $2 - /, $3 - *.for, значе-
ния остальных позиционных переменных будут пустыми строками.
Заметим, что если бы символ * при вызове ficofl не был экрани-
рован, в качестве аргументов передались бы имена всех фортран-
ных файлов текущей директории.
Еще две переменные хранят командную строку за исключением
имени команды: $@ эквивалентно $1 $2 ..., а $* - "$1 $2 ...".
Начальные значения переменным с именем могут быть установ-
лены следующим образом:

<имя>=<значение> [ <имя>=<значение> ] ...

Не может быть одновременно функции (см. Управляющие конструк-
ции) и переменной с одинаковыми именами.
Для подстановки значений переменных возможны также следую-
щие конструкции:

${<переменная>}

если значение <переменной> определено, то оно подставляется.
Скобки применяются лишь если за <переменной> следует символ,
который без скобок приклеится к имени.

${<переменная>:-<слово>}

если <переменная> определена и не является пустой строкой, то
подставляется ее значение; иначе подставляется <слово>.

${<переменная>:=<слово>}

если <переменная> не определена или является пустой строкой, ей
присваивается значение <слово>; после этого подставляется ее
значение.

${<переменная>:?<слово>}

если <переменная> определена и не является пустой строкой, то
подставляется ее значение; иначе на стандартный вывод выводится
<слово> и выполнение shellа завершается. Если <слово> опущено,
то выдается сообщение "parameter null or not set".

${<переменная>:+<слово>}

если <переменная> определена и не является пустой строкой, то
подставляется <слово>; иначе подставляется пустая строка.

Пример: если переменная d не определена или является пус-
той строкой, то выполняется команда pwd

echo ${d:-`pwd`}

Следующие переменные автоматически устанавливаются shellом:

# количество позиционных параметров (десятичное)
- флаги, указанные при запуске shellа или коман-
дой set
? десятичное значение, возвращенное предыдущей
синхронно выполненной командой
$ номер текущего процесса
! номер последнего асинхронного процесса
@ эквивалентно $1 $2 $3 ...
* эквивалентно "$1 $2 $3 ..."

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

echo $$

    2_4. Специальные переменные



Shellом используются следующие специальные переменные:

HOME директория, в которую пользователь попадает при
входе в систему или при выполнении команды cd
без аргументов
PATH список полных имен каталогов, в которых ищется
файл при указании его неполного имени.
PS1 основная строка приглашения (по умолчанию $)
PS2 дополнительная строка приглашения (по умолчанию
>); в интерактивном режиме перед вводом команды
shellом выводится основная строка приглашения.
Если нажата клавиша new_line, но для завершения
команды требуется дальнейший ввод, то выводится
дополнительная строка приглашения
IFS последовательность символов, являющихся разде-
лителями в командной строке (по умолчанию это
<пробел>, <табуляция> и <возврат_каретки>)

    * 3_ Управляющие конструкции *



Простая команда - это последовательность слов, разделенная
пробелами. Первое слово является именем команды, которая будет
выполняться, а остальные будут переданы ей как аргументы. Имя
команды передается ей как аргумент номер 0 (т.е. имя команды
является значением $0). Значение, возвращаемое простой командой
- это ее статус завершения, если она завершилась нормально, или
(восьмеричное) 200+статус, если она завершилась аварийно.
Список - это последовательность одного или нескольких кон-
вейеров, разделенных символами ;, &, && или || и быть может за-
канчивающаяся символом ; или &. Из четырех указанных операций ;
и & имеют равные приоритеты, меньшие, чем у && и ||. Приоритеты
последних также равны между собой. Символ ; означает, что кон-
вейеры будут выполняться последовательно, а & - параллельно.
Операция && (||) означает, что список, следующий за ней будет
выполняться лишь в том случае, если код завершения предыдущего
конвейера нулевой (ненулевой).
Команда - это либо простая команда, либо одна из управляю-
щих конструкций. Кодом завершения команды является код заверше-
ния ее последней простой команды.

    3_1. Цикл ДЛЯ



for <переменная> [ in <набор> ]
do
<список>
done

Если часть in <набор> опущена, то это означает in "$@" ( то
есть in $1 $2 ... $n). Пример. Вывести на экран все фортранные
файлы текущей библиотеки:

for f in *.for
do
cat $f
done

    3_2. Оператор выбора



case $<переменная> in
<шаблон> | <шаблон>... ) <список> ;;
. . .
esac

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

Пример. Определить флаги и откомпилировать все указанные файлы.

# инициализировать флаг
flag=

# повторять для каждого аргумента
for a
do
case $a in

# объединить флаги, разделив их пробелами
-[ocSO]) flag=$flag' ' $a ;;
-*) echo 'unknown flag $a' ;;

# компилировать каждый исходный файл и сбросить флаги
*.c) cc $flag $a; flag= ;;
*.s) as $flag $a; flag= ;;
*.f) f77 $flag $a; flag= ;;

# неверный аргумент
*) echo 'unexpected argument $a' ;;
esac
done

    3_3. Условный оператор.



if <список1>
then
<список2>
[ elif <список3>
then
<список4> ]
. . .
[ else
<список5> ]
fi

Выполняется <список1> и, если код его завершения 0, то выполня-
ется <список2>, иначе - <список3> и, если и его код завершения
0, то выполняется <список4>. Если же это не так, то выполняется
<список5>. Части elif и else могут отсутствовать.

    3_4. Цикл ПОКА



while <список1>
do
<список2>
done

До тех пор, пока код завершения последней команды <списка1>
есть 0, выполняются команды <списка2>.
При замене служебного слова while на until условие выхода
из цикла меняется на противоположное.
В качестве одной из команд <списка1> может быть команда
true (false). По этой команде не выполняется никаких действий,
а код завершения устанавливается 0 (-1). Эти команды применяют-
ся для организации бесконечных циклов. Выход из такого цикла
можно осуществить лишь по команде break (см. Специальные коман-
ды).

    3_5. Функции



<имя> () {
<список>;
}

Определяется функция с именем <имя>. Тело функции - <список>,
заключенный между { и }.

    3_6. Зарезервированные слова



Следующие слова являются зарезервированными:

if then else elif fi
case in esac
for while until do done
{ }

    3_7. Специальные команды



Как правило, для выполнения каждой команды shell порождает
отдельный процесс. Специальные команды отличаются тем, что они
встроены в shell и выполняются в рамках текущего процесса.

: Пустая команда. Возвращает нулевой код заверше-
ния.
. file Shell читает и выполняет команды из файла file,
затем завершается; при поиске file используется
список поиска $PATH.
break [n] Выход из внутреннего for или while цикла; если
указано n, то выход из n внутренних циклов.
continue [n] Перейти к следующей итерации внутреннего for
или while цикла; если указано n, то переход к
следующей итерации n-ого цикла.
cd [ <аргумент> ]
Сменить текущую директорию на директорию <аргу-
мент>. По умолчанию используется значение HOME.
echo [ <арг> ... ]
Выводит свои аргументы в стандартный вывод,
разделяя их пробелами.
eval [ <арг> ... ]
Аргументы читаются, как если бы они поступали
из стандартного ввода и рассматриваются как ко-
манды, которые тут же и выполняются.
exec [ <арг> ... ]
Аргументы рассматриваются как команды shellа и
тут же выполняются, но при этом не создается
нового процесса. В качестве аргументов могут
быть указаны направления ввода-вывода и, если
нет никаких других аргументов, то будет измене-
но лишь направление ввода-вывода текущей прог-
раммы.
exit [ n ] Завершение выполнения shellа с кодом завершения
n. Если n опущено, то кодом завершения будет
код завершения последней выполненной команды
(конец файла также приводит к завершению выпол-
нения).
export [ <переменная> ... ]
Данные переменные отмечаются для автоматическо-
го экспорта в окружение (см. Окружение) выпол-
няемых команд. Если аргументы не указаны, то
выводится список всех экспортируемых перемен-
ных. Имена функций не могут экспортироваться.
hash [ -r ] [ <команда> ... ]
Для каждой из указанных команд определяется
и запоминается путь поиска. Опция -r удаляет
все запомненные данные. Если не указан ни один
аргумент, то выводится информация о запомненных
командах: hits - количество обращений shellа к
данной команде; cost - объем работы для обнару-
жения команды в списке поиска; command - полное
имя команды. В некоторых ситуациях происходит
перевычисление запомненных данных, что отмеча-
ется значком * в поле hits.
pwd Выводит имя текущей директории.
read [ <переменная> ... ]
Читается из стандартного ввода одна строка;
первое ее слово присваивается первой перемен-
ной, второе - второй и т.д., причем все остав-
шиеся слова присваиваются последней перемен-
ной.
readonly [ <переменная> ... ]
Запрещается изменение значений указанных пере-
менных. Если аргумент не указан , то выводится
информация обо всех переменных типа readonly.
return [ n ] Выход из функции с кодом завершения n. Если n
опущено, то кодом завершения будет код заверше-
ния последней выполненной команды.
set [ --aefkntuvx [ <арг> ... ] ]
Команда устанавливает следующие режимы:

-a отметить переменные, которые были изменены или
созданы, как переменные окружения (см. Окруже-
ние)
-e если код завершения команды ненулевой, то не-
медленно завершить выполнение shellа
-f запретить генерацию имен файлов
-k все переменные с именем помещаются в окружение
команды, а не только те, что предшествуют имени
команды (см. Окружение)
-n читать команды, но не выполнять их
-t завершение shellа после ввода и выполнения од-
ной команды
-u при подстановке рассматривать неустановленные
переменные как ошибки
-v вывести вводимые строки сразу после их ввода
-x вывести команды и их аргументы перед их выпол-
нением
-- не изменяет флаги, полезен для присваивания по-
зиционным переменным новых значений.

При указании + вместо - каждый из флагов уста-
навливает противоположный режим. Набор текущих
флагов есть значение переменной $-. <арг> - это
значения, которые будут присвоены позиционным
переменным $1, $2 и т.д. Если все аргументы
опущены, выводятся значения всех переменных.

shift [ n ] Позиционные переменные, начиная с $(n+1), пере-
именовываются в $1 и т.д. По умолчанию n=1.
test вычисляет условные выражения (см. Дополнитель-
ные сведения. Test )
trap [ <арг> ] [ n ] ...
Команда <арг> будет выполнена, когда shell по-
лучит сигнал n (см. Сигналы). (Надо заметить,
что <арг> проверяется при установке прерывания
и при получении сигнала). Команды выполняются
по порядку номеров сигналов. Любая попытка ус-
тановить сигнал, игнорируемый данным процессом,
не обрабатывается. Попытка прерывания по сигна-
лу 11 (segmentation violation) приводит к ошиб-
ке. Если <арг> опущен, то все прерывания уста-
навливаются в их начальные значения. Если <арг>
есть пустая строка, то этот сигнал игнорируется
shellом и вызываемыми им программами. Если n=0,
то <арг> выполняется при выходе из shellа. Trap
без аргументов выводит список команд, связанных
с каждым сигналом.
type [ <имя> ... ]
Для каждого имени показывает, как оно будет ин-
терпретироваться при использовании в качестве
имени команды: как внутренняя команда shellа,
как имя файла или же такого файла нет вообще.
ulimit [ -f ] [ n ]
Устанавливает размер файла в n блоков; -f - ус-
танавливает размер файла, который может быть
записан процессом-потомком (читать можно любые
файлы). Без аргументов - выводит текущий раз-
мер.
umask [ nnn ] Пользовательская маска создания файлов изменя-
ется на nnn. Если nnn опущено, то выводится те-
кущее значение маски. Пример: после команды
umask 755
будут создаваться файлы, которые владелец смо-
жет читать, писать и выполнять, а все остальные
- только читать и выполнять.
unset [ <имя> ... ]
Для каждого имени удаляет соответствующую пере-
менную или функцию. Переменные PATH, PS1, PS2 и
IFS не могут быть удалены.
wait [ n ] Ждет завершения указанного процесса и выводит
код его завершения. Если n не указано, то ожи-
дается завершения всех активных процессов-по-
томков и возвращается код завершения 0.

    * 4_ Выполнение shell-программ *



    4_1. Запуск shellа



Программа, интерпретирующая shell-программы, находится в
файле /bin/sh. При запуске ее первый аргумент является именем
shell-программы, остальные передаются как позициональные пара-
метры. Если файл, содержащий shell-программу, имеет право вы-
полнения (x), то достаточно указания лишь его имени. Например,
следующие две команды операционной системы эквивалентны (если
файл ficofl обладает указанным правом и на самом деле содержит
shell-программу):

sh ficofl -d . g\*
и
ficofl -d . g\*

    4_2. Выполнение



При выполнении shell-программ выполняются все подстановки.
Если имя команды совпадает с именем специальной команды, то она
выполнается в рамках текущего процесса. Так же выполняются и
определенные пользователем функции. Если имя команды не совпа-
дает ни с именем специальной команды, ни с именем функции, то
порождается новый процесс и осуществляется попытка выполнить
указанную команду.
Переменная PATH определяет путь поиска директории, содер-
жащей данную команду. По умолчанию это

::/bin:/usr/ bin:/util:/dss/rk

Директории поиска разделяются двоеточиями; :: означает текущую
директорию. Если имя команды содержит символ /, значение $PATH
не используется: имена, начинающиеся с / ищутся от корня, ос-
тальные - от текущей директории. Положение найденной команды
запоминается shellом и может быть опрошено командой hash.

    4_3. Окружение



Окружение - это набор пар имя-значение, которые передаются
выполняемой программе. Shell взаимодействует с окружением нес-
колькими способами. При запуске shell создает переменную для
каждой указанной пары, придавая ей соответствующее значение.
Если вы измените значание какой-либо из этих переменных или
создадите новую переменную, то это не окажет никакого влияния
на окружение, если не будет использована команда export для
связи переменной shellа с окружением (см. также set -a). Пере-
менная может быть удалена из окружения командой unset (см.).
Таким образом, окружение каждой из выполняемых shellом команд
формируется из всех неизмененных пар имя-значение, первоначаль-
но полученных shellом, минус пары, удаленные командой unset,
плюс все модифицированные и измененные пары, которые для этого
должны быть указаны в команде export.
Окружение простых команд может быть сформировано указанием
перед ней одного или нескольких присваиваний переменным. Так,

TERM=d460 <команда>

и

(export TERM; TERM=d460; <команда>)

эквивалентны. Переменные, участвующие в таких присваиваниях,
назовем ключевыми параметрами.
Если установлен флаг -k (см. set), то все ключевые пара-
метры помещаются в окружение команды, даже если они записаны
после команды.

    4_4. Сигналы



UNIXом поддерживаются следующие сигналы:

SIGHUP - 1 - отменить (hangup)
SIGINT - 2 - прерывание (interrupt)
SIGQUIT - 3 - нестандартный выход (quit)
SIGILL - 4 - неверная команда (illegal instruction)
SIGTRAP - 5 - ловушка (trace trap)
SIGFPE - 8 - исключительная ситуация при выполнении операций
с плавающей запятой (floating-point exception)
SIGKILL - 9 - уничтожение процесса (kill)
SIGBUS - 10 - ошибка шины (bus error)
SIGSEGV - 11 - нарушение сегментации (segmentation violation)
SIGSYS - 12 - неверный системный вызов (bad argument to sys-
tem call)
SIGPIPE - 13 - запись в канал без чтения из него (write on a
pipe with no one to read it)
SIGALRM - 14 - будильник (alarm clock)
SIGTERM - 15 - программное завершение процесса (software ter-
mination signal)

Сигналы SIGINT и SIGQUIT игнорируются, если команда была
запущена асинхронно. Иначе сигналы обрабатываются так же, как в
процессе-предке, за исключением сигнала SIGSEGV (см. также Спе-
циальные команды. Trap).

    4_5. Замечания



При выполненнии команд запоминается их местонахождение.
Поэтому при создании команды с тем же именем, но находящейся в
другой директории, все равно будет выполняться старая команда
(если вызов происходит по короткому имени). Для исправления си-
туации воспользуйтесь командой hash с ключом -r (см. Специаль-
ные команды).
Если вы переименовали текущую или вышележащую директорию,
то команда pwd может давать неверную информацию. Для исправле-
ния ситуации воспользуйтесь командой cd с полным именем дирек-
тории.

    * 5_ Дополнительные сведения *



    5_1. Команда test



Команда test применяется для проверки условия. Формат вы-
зова:
test <выражение>

или

[ <выражение> ]

Команда test вычисляет <выражение> и, если его значение - исти-
на, возвращает код завершения 0 (true); иначе - ненулевое зна-
чение (false). Ненулевой код завершения возвращается и если
опущены аргументы. <Выражение> может состоять из следующих при-
митивов:

-r файл - истина, если файл существует и доступен для
чтения
-w файл - истина, если файл существует и доступен для
записи
-x файл - истина, если файл существует и является вы-
полняемым
-f файл - истина, если файл существует и является обыч-
ным файлом
-d файл - истина, если файл существует и является ди-
ректорией
-c файл - истина, если файл существует и является спе-
циальным символьно-ориентированным файлом
-b файл - истина, если файл существует и является спе-
циальным блок-ориентированным файлом
-p файл - истина, если файл существует и является име-
нованным каналом (pipe)
-s файл - истина, если файл существует и имеет ненуле-
вую длину
-t [ дескриптор файла ]
- истина, если открытый файл с указанным деск-
риптором (по умолчанию 1) существует и ассоции-
рован с терминалом
-zho s1 - истина, если длина строки s1 нулевая
-n s1 - истина, если длина строки s1 ненулевая
s1 = s2 - истина, если строки s1 и s2 совпадают
s1 != s2 - истина, если строки s1 и s2 не совпадают
s1 - истина, если s1 непустая строка
n1 -eq n2 - истина, если целые n1 и n2 алгебраически сов-
падают . На месте -eq могут быть также -ne,
-gt, -ge, -lt, -le

    5_2. Команда expr



Команда expr применяется для вычисления выражений. Резуль-
тат выводится на стандартный вывод. Операнды выражения должны
быть разделены пробелами. Метасимволы должны быть экранированы.
Надо заметить, что 0 возвращается в качестве числа, а не для
индикации пустой строки. Строки, содержащие пробелы или другие
специальные символы, должны быть заключены в кавычки. Целые
рассматриваются как 32-битные числа.
Ниже приведен список операторов в порядке возврастания
приоритета, операции с равным приоритетом заключены в фигурные
скобки. Перед символами, которые должны быть экранированы, сто-
ит \.

<выр> \| <выр>
если первое <выр> не пустое и не нулевое, то
возвращает его, иначе возвращает второе <выр>
<выр> \& <выр>
если оба <выр> не пустые и не нулевые, то
возвращает первое <выр>, иначе возвращает 0
<выр> { =, \>, \>=, \<, \<=, != } <выр>
возвращает результат целочисленного сравнения
если оба <выр> - целые; иначе возвращает ре-
зультат лексического сравнения
<выр> { +, - } <выр>
сложение и вычитание целочисленных аргументов
<выр> { \*, /, % } <выр>
умножение, деление и получение остатка от деле-
ния целочисленных аргументов
<выр> : <выр>
оператор сопоставления : сопоставляет первый
аргумент со вторым, который должен быть регу-
лярным выражением. Обычно оператор сравнения
возвращает число символов, удовлетворяющих об-
разцу (0 при неудачном сравнении). Однако сим-
волы \( и \) могут применяться для выделения
части первого аргумента.

Регулярное выражение строится следующим образом:
. - обозначает любой символ
* - обозначает предыдущий символ, повторенный несколько
раз
[] - обозначают любой один из указанных между ними симво-
лов; группа символов может обозначаться с помощью
знака "-" (т.е. [0-9] эквивалентно [0123456789]); ес-
ли после [ стоит ^, то это эквивалентно любому симво-
лу, кроме указанных в скобках и <возврата_каретки>;
для указания ] в качестве образца, надо поставить ее
сразу за [ (т.е. []...]); . и * внутри квадратных
скобок обозначают самих себя
Все остальные символы (и ^, если стоит не в квадратных скобках)
обозначают самих себя. Для указания символов ., *,[ и ] надо
экранировать их (т.е. писать \., \*, \[, \]).

Примеры.
1. a=`expr $a + 1`
- увеличение на 1 переменной a
2. expr $a : '.*/\(.*\)' \| $a
- выделяет из имени файла короткое имя (т.е. из
/usr/util/ena выделяется ena). Внимание,
одиночный символ / будет воспринят как знак
операции деления.
3. expr $VAR : '.*'
- получение количества символов переменной VAR.

В качестве побочного эффекта expr возвращает следующие коды за-
вершения:
0 - если выражение не нуль и не пустая строка
1 - если выражение нуль или пустая строка
2 - для некорректных выражений
Команда expr также выдает следующие сообщения об ошибках:
syntax error - для ошибок в операторах или операндах
non-numeric argument - для попыток применения арифметических
операций к нечисловым строкам

Замечание.
Допустим, что мы хотим сравнить значение переменной a с
каким-либо символом, имеющим для expr особый смысл, например,
со знаком равенства. Пусть $a на самом деле является знаком ра-
венства. Так как аргументы предварительно обрабатываются shel-
lом, то команда

expr $a = '='

будет воспринята как

expr = = =

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

expr X$a = X=

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

    5_3. Команда ena



Команда ena позволяет получить части полного имени файла.
Первый аргумент - флаг, второй - имя файла. Команда различает
следующие флаги:
-n - имя файла без расширения
-f - имя файла с расширением
-e - расширение
-d - имя директории
-p - если имя файла начинается с . или .. , то эти
символы выделяются из имени

Ниже приводится текст программы ena, хранящийся в /util/ena.

# Get part of pathname

case $1 in
-n )
expr $2 : '.*/\(.*\)[.].*' \| $2 : '\(.*\)[.].*' \| $2
;;
-f )
expr $2 : '.*/\(.*\)' \| $2
;;
-e )
expr $2 : '.*\([.][^./]*\)' \| ' '
;;
-d )
expr $2 : '\(.*\)/.*' \| $2
;;
-p )
expr $2 : '\([.]\)/.*' \| $2 : '\([.][.]\)/.*' \| ' '
;;
* )
echo "error: unknown part of pathname $1"
exit 2
;;
esac


Источника -http://lib.ru/unixhelp/unixshell.txt

Монтируем ISO в Linux

[announce]Из-за слабой памяти сделал себе заметку о том как примонтировать iso в linux, чтобы лишний раз не тревожить гугл, может кому еще пригодиться[/announce]
Для того, чтобы примонтировать iso в Linux нужно для начало создать место куда будем монтировать

mkdir /mnt/iso

И дать команду

mount fileiso.iso /mnt/iso/ -t iso9660 -o ro,loop=/dev/loop0

fileiso.iso — образ

Своровано с blogpost.am9.ru

Куда пропал mkfs.vfat в ARCHLinux ??

[announce]Недавно понадобилось отформатировать раздел в fat под арчи, на команду mkfs.vfat получил многозначительный ответ — command not found: mkfs.vfat[/announce]
  Собственно суть в том, что под archlinux не оказалось команды для форматирования разделов в fatmkfs.vfat
Гугл подсказал мне страницу на которой я нашел решение. Выкладываю его сюда, что бы те у кого возникнет та же проблема, смогли найти ее решение на моем сайте. Все дело в двух пакетах, которые по-умолчанию не установлены в системе: dosfstools, ntfsprogs.

Устанавливаем —

pacman -S dosfstools
pacman -S ntfsprogs

Первый пакет даст нам команду mkfs.vfat, mkfs.msdos Второй пакет даст нам команду mkfs.ntfs

Источник

ГАВк

[announce]Инструменты прикладного программиста: строковый процессор awk. Описано популярное инструментальное средство среды программиста в UNIX: строковый процессор awk, позволяющий эффективно обрабатывать различную текстовую информацию. Предназначена для прикладных программистов, специалистов по информатике и студентов, специализирующихся в информационных технологиях. [/announce]

Cтроковый процессор awk

Е.А. Нурминский
Благовещенск1998

Содержание:

Что такое строковый процессор awk

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

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

Это процессор рассматривает входной поток данных как состоящий из записей, разделенными специальными символами (RS). По умолчанию таким символом является символ перехода на новую строку (‘\n‘). Запись считается разделенной ( символами FS)1 на поля и строковый процессор awk автоматически выделяет эти поля и дает возможность производить с ними различные операции. По сути дела, это единственное предположение, которое делает awk относительно структуры входных данных.

Задание процесса обработки некоторого файла с помощью программы awk состоит в описании действий, которые нужно произвести с записями и полями. Для этого awk предоставляет в распоряжение программиста развитый язык программирования, напоминающий популярный язык программированияC. Это и не удивительно, так как авторы awk (Альфред В. Ахо ( Alfred V. Aho — a), Питер Дж. Вайнбергер ( Peter J. Weinberger — w ) и Брайан У. Кернихан ( Brian W. Kernighan — k) известны как родоначальники языка C и операционной системы UNIX.

Входной язык процессора awk является в определенном смысле »упрощенным» C и не содержит таких типов данных как указатели и структуры. Отсутствуют в нем и другие элементы языка C, такие, напримерa, как команды препроцессора, битовые операции, локализация переменных и пр.

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

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

Структура awk-файла

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

Программа на awk может содержать определения функций, которые можно считать также имеющими форму образец — действие со специальным видом образца. Подробнее задание функций описано в разделе [*]

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

Образцы и регулярные выражения

Для задания образцов используются следующие средства:

 

/регулярное выражение/
логическое выражение
проверка на совпадение
диапазон записей
заголовок функции
BEGIN
END

 

 

Понятие регулярного выражения совпадает в основном с регулярными выражениями, признаваемыми grep[1], что неудивительно, так как авторы awk сильно повлияли и на разработку grep.

Простейшим случаем регулярного выражения является строка символов. Программа ( с пустым действием )

    /Иванов/

напечатает из текстового файла те строки, которые содержат подстроку"Иванов" ( в том числе и "Ивановский машиностроительный завод" ).

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

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

Канонический список метасимволов содержит следующие элементы:

 

^ $ [ ] - + * .(точка) \

 

Метасимволы имеют следующую сематику:

^ — соответствует началу строки. Это позволяет выделять строки не только по наличию в них тех или иных символов, но и по их расположению в строке. Так, например, /^A/ соответствует строкам (записям), начинающимся на A.
$ — соответствует концу строки. Например,/A$/ отвечает строкам, заканчивающимся на A.
[ ] — c помощью этих символов описывают множества единичных символов. В простейшем случае эти множества описываются перечислением: [AWK]соответствует множеству из трех букв A, W, K. Соответственно G[AWK] представляет множество строк{ GA, GW, GK }.
- — используется для задания диапазона символов, например,[a-z] соответствует символам от a до z, как они расположены в таблице кодов ASCII.
+ — этот символ обозначает многократное ( не менее одного ) повторение в образце символа, предшествующего +.
* — также многократное, но возможно также и нулевое повторение предыдущего символа. Типичный пример: [1-9][0-9]* — положительные целые числа.
.(точка) — обозначает произвольный единичный символ. Легендарную известность приобрела комбинация .*, которая обозначает таким образом произвольную комбинацию символов.
\ — отменяет специальное значение последующего символа. Отмена специального значения \ производится при помощи \\.

Логические выражения строятся с помощью операций, приведенных в табл. [*].

 

Table:Логические операции языка awk.
|| логическое или
&& логическое и
<, <= меньше, меньше или равно
>=, > больше, больше или равно
== совпадение (строк) или численное равенство
!= несовпадение или неравенство
~ проверка на содержание
! отрицание

Например, образец /^A/ && ! /^AB/соответствует записям, начинающимся на символ A, но не имеющим в качестве последующего символа B.

В качестве образца можно указать также и группу строк. Такая группа строк обозначается в поле образца как

    образец-1, образец-2

и означает, что соответствующее действие будет выполнятся для строк, которым предшествовала строка, соответствующаяобразец-1, но предшествующим строке, соответствующейобразец-2.

Специальные символы BEGIN, END обозначают начало и конец файла ввода. С их помощью можно выполнить до начала действительной работы awk желаемые действия по настройке awk, а по завершению работы — выдать какую-либо итоговую информацию.

Действия awk

Действия awk представляюют собой последовательность операций, записаных на языке awk и заключенных в фигурные скобки. Простейшим вариантом действия является комбинация {}, которая по соглашению awk вызывает печать текущей строки (записи). Вокруг пустого действия скобки необязательны, если в пареобразец—действие присутствует нетривиальный образец. Если образец пуст, то присутствие фигурных скобок обязательно.

Тело действия в awk представляет собой программу на языке awk, в котором присутствуют многие из аттрибутов языка программирования: присвоения, выражения, условные операторы, циклы, операторы ввода-вывода, команды работы с файловой системой и пр. Команды awk могут группироваться с помощью тех же самых фигурных скобок {} и образовывать составные операторы.

К восторгу поклонников структурного программирования в awk отсутствует оператор GOTO и метки.

Подробнее команды awk рассмотрены в следующем разделе.

Команды awk

После того, как awk прочел очередную запись и разделил ее на поля, содержимое этих полей становиться доступным как значения специальных переменных 2, .... При этом$1 соответствует первому полю,$2 — второму и т.д. Далее с этими переменными могут быть произведены различные операции, используя набор команд awk. Программа awk предоставляет пользователю широкий набор команд, обеспечивающий выполнение достаточно полного репертуара операций с вводимыми данными.

Ввод данных в awk

По умолчанию awk читает с устройства стандартного ввода (клавиатура), однако может читать и подготовленный заранее файл данных или конвейерный вывод другой программы.

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

Эти базовые возможности awk по вводу данных могут быть существенно расширены использованием функции (или команды) getline.

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

TOP SECRET!  NEXT LINE TO BE BURNED BEFORE READING!

После выполнения команды getlineawk продолжает нормальный цикл своей деятельности, применяя к этой записи последующие пары образец — действие.

Команда getline может быть использована для ввода значения строковой переменной:

    getline message

Никаких побочных эффектов при этом не происходит, за исключением того, что изменяется счетчик записей NR.

Команда getline может читать из поименованного файла, используя технику перенаправления:

    getline < file

Выражение file может быть произвольным строковым выражением, которые интерпретируются как имя файла в данной операционной системе.

Если getline не встретила каких-либо проблем при исполнении, она возвращает значение 1. Если при исполнении обнаружен конец файла, то возвращается 0, если обнаружена ошибка, то возвращается -1. В последнем случае причину ошибки можно найти, проанализировав значение переменной ERRNO.

Печать (вывод) данных

Одна из наиболее употребительных операций с вводимыми данными — это их печать, возможно селективная и сопровождаемая некоторыми простейшими преобразованиями. Для печати awk использует операторыprint, printf, sprints. Простейший из них — print имеет синтаксис

    print a,b,c, ... z

где a, b, c, ..., z это список вывода, который может включать различные строковые и арифметические выражения.

Например, в результате исполнения оператора

    print exp(1)

будет напечатано число

2.71828

а в результате выполнения оператора

    print "Вася" "+" "Маша"

будет напечатана строка

Вася+Маша

Обратите внимание, что напечаталась конкатенированная строка, т.е."Вася" "+" "Маша"представляет собой строковое выражение, значением которого является строка"Вася+Маша".

Если печать будет производиться оператором

    print "Вася","+","Маша"

результат будет обычно выглядеть как

Вася + Маша

Значения списка вывода разделены в этом случае пробелом, которые является значением по умолчанию специальной внутренней переменнойOFS. Эта и другие специальные переменные awk будут рассмотрены позднее, а пока заметим, что значение OFS может быть изменено пользователем. Например, если определить OFS="\n", то тот же оператор печати выдаст результат

Вася+Маша

Оператор

    print $1

выведет на печать содержимое первого, а оператор

    print $NF

последнего поля текущей записи.

По умолчанию для вывода чисел awk использует в качестве формата значение специальной внутренней переменной OFMT, оычно имеющей значение "%.6g". Изменив это значение, можно изменить форму вывода чисел, например,OFMT="%.0f"будет выводить все числа как целые, округляя их до ближайшего.

Операторы printf, sprintf осуществляют форматированый вывод в духе операторов вывода языка C. Для этих операторов первым элементом списка вывода является строка, содержащая описание форматов вывода последующих элементов списка. Для описания форматов применимы стандартные правила языка C:

%s строка символов
%d десятичное целое
%f вещественное число с десятичной точкой
%o восьмеричное число
%x шестнадцатиричное число

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

Предопределенные разделители OFS, ORS не влияют на вывод, осуществляемый посредством printf, в частности в конце записи не добавляется автоматически символ перехода на новую строку ( значение ORS по умолчанию ).

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

    pi = sprintf("%f10.6", 4*atan(1))

присваивает строковой переменной pi значение " 3.141592".

Вывод операторов print, printf может быть перенаправлен стандартным для UNIX образом. Целью такого перенааправления может служить какой-либо поименованный файл или другая команда операционной системы. В случае файла результат команды print или printfможет либо затирать предыдущее содержание файла, либо дописываться к нему. Первое осуществляется командой

    print "Вася+Маша" > "message.of.the.day"

а второе — командой

    print "Вася+Маша" » "message.of.the.day"

Следует иметь в виду, что различие между этими вариантами перенаправления существует лишь до открытия файла message.of.the.day и первой операции записи в этот файл. Последующие перенаправления будут давать тот же результат: новые порции выводимой информации будут дописываться к содержанию файла. Если это нежелательно, необходимо в явном виде закрывать файл с помощью оператора close, рассмотренного ниже.

Программа awk допускает также и перенаправление вывода в конвейер. В этом случае опреатор вывода имеет вид

    printf A, B, C, ... | CMD

где команда CMD может быть произвольным строковым выражением. Значение этого строкового выражения передается комадному интерпретатору операционной системы для исполнения.

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

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

close (filename) закрыть файл filename
close (COMMAND) закрыть конвейер COMMAND.

Как это принято в UNIX, awk направляет вывод по каналу стандартного вывода stdout. Для вывода по каналу ошибок stderr нужно что-то вроде

    print "ERROR" | " cat 1 > & 2"

В разных версиях awk используются разные трюки для работы с каналами. В частности, в GAWK используются специальные имена, приведенные в табл. [*].

 

Table:Описатели стандартных каналов ввода-вывода
Имя канала fd
/dev/stdin 0
/dev/stdout 1
/dev/stderr 2

Для работы с файлом, имеющим описатель N, используется также символическое имя /dev/fd/N

.

 

Условное выполнение

Условное выполнение осуществляется с помощью оператораif-then-else имеющего в общем случае следующую форму:

 
if (условие) then { действие-1 }
else { действие-2 }

Если действие-1 или -2 содержит один единственный оператор, фигурные скобки не требуются.

К некоторой трудно объяснимой особенности awk относится то, что если действие-1 содержит один операнд, то за ним должна следовать точка с запятой (;).

Циклы

awk содержит хорошо известный C-программистам набор операторов цикла: do-while, while, for

.

Цикл do-while имеет вид

do {    тело цикла} while (условие)

где тело цикла используется по крайней мере один раз и до тех пор пока условие остается истинным.

Цикл while имеет вид

while (условие) {      тело цикла}

и проверка условия осуществляется до исполнения тела цикла.

Цикл for имеет две формы в awk: одна — традиционная:

for(инициализация; условия; завершение){    тело цикла}

и вторая — ассоциативная:

for(index in list){    тело цикла}

где list — ассоциативный массив, подробности работы с которыми будут рассмотрены ниже. На содержательном уровне вторая форма оператора for означает использование тела цикла для каждого элемента ассоциативного массива list. Порядок исполнения непредсказуем.

В приведенных конструкциях фигурные скобки {} необязательны если тело цикла представляет собой один оператор.

В отличие от Cязык awk содержит две формы операторов досрочного прерывания цикла и досрочного перехода к следующему выполнению тела цикла. Это связано с тем, что сама конструкция awk подразумевает неявный внешний цикл: чтение данных — обработка.

Для досрочного прекращения этого процесса обработки служит операторexit. Он по сути дела эквивалентен прерыванию текущих операций обработки и чтению признака конца входного файла (EOF для C-патриотов). Если в awk-программе есть действия, ассоциированные с образом END, они будут выполнены.

Для досрочного прерывания процесса обработки текущей записи (и запуска новой операции чтения — обработки) служит оператор next. Для управления циклами, в явном виде содержащимися вawk-программах, служат операторы break, continue. Оператор breakпрекращает выполнение цикла, continue запускает новое исполнение тела цикла.

К операторам управления последовательностью операций с некоторой натяжкой можно отнести и return — оператор возврата из функции, описанной программистом. Оператор

    return выражение

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

Массивы

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

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

    { payoff[7 }

и проблема остается лишь в выводе значений массива payoffпо завершению работы программы.

Конечно, для такого понятия массива трудно ввести предварительное декларирование и элементы массивов в awk создаются в момент использования. По исчерпыванию необходимости в этом элементе, от него можно в явном виде избавиться при помощи оператораdelete:

    delete payoff["Иванов"]

и освободить память для более важных дел. Удалить весь массив payoff можно командой

    delete payoff

Определение множества индексов данного массива и обход элементов массива можно произвести с помощью ассоциативного цикла, уже упомянутого выше. Отрывок awk-программы

END	{	for(name in payoff)		printf name, payoff[name]	}

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

Единственным недостатком такого простого решения являетя неопределенный порядок индексов массива payoff, в связи с чем их имена почти наверняка не будут выведены в алфавитном порядке !

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

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

Например, оператор

    n = split("31.12.1999", date, ".")

разобьет строку "31.12.1999" на три части"31", "12", "1999", используя в качестве разделителя символ "."и присвоит массиву date значения:

date[1] = "31", date[2] = "12", date[3] = "1999".

Переменной n присвоится, конечно, значение 3.

Если функция split вызывается с двумя аргуменами, подразумевается, что символом-разделителем является значение встроенной переменной awkFS — по умолчанию пробельный символ.

Таким образом

    nn = split($0, tokens)

в явном виде выполнит ту работу, что awk делает по умолчанию: разделит входную строку ($0) на отдельные элементы и запишет их в массив tokens. Количество элементов будет запомнено, как значение переменной nn.

Это полностью эквивалентно явному циклу

	for(i = 1; i <= NF; i++)		tokens[i] = $i	nn = NF

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

Функции

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

Встроенные функции

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

Их основные характеристики приведены в табл. [*].

Таблица [*]. Встроенные функции языка awk
   
Численные функции
   
atan2 арктангенс
cos косинус
exp экспонента
int целочисленное округление
log натуральный логарифм
rand псевдослучайное число из интервала
sin синус
sqrt квадратный корень
srand инциализация случайного датчика
Строковые функции
   
sub, gsub выделение подстроки
index поиск мета в строке
length длина строки
match проверка на наличие подстроки
split разбивка строки на элементы
substr выделение подстроки
tolower перевод в нижний регистр
toupper перевод в верхний регистр
Функции, определяющие системное время
systime() возвращает число секунд, прошедших со времени некоторого знаменательного с точки зрения оперционной системы события. На POSIX-стандартных системах это время, прошедшее с полночи 1 января 1979 г. по Гринвичу.
strftime() возвращает строковое значение временной меткиTIME (второй аргумент) в соответствии с форматом FORMAT(первый аргумент). Детали слишком утомительны, чтобы их излагать в таком малом обьеме.
Разное
   
system(s) строка s интерпретируется как команда операционной системы и исполняется командным интерпретатором.

Численные функции имеют вполне традиционный смысл, за исключением, пожалуй, atan2(x,y) , которая вычисляет для и равна для . Значение atan2(0, 0) = 0.

Генератор случайных чисел rand() может быть проинициализирован с помощью функции srand(x). По умолчанию в качестве x используется время дня. Если rand() не инициализаруется, то при повторном исполнении awk-программы генерируется та же самая последовательность чисел.

Строковые функции имеют следующий синтаксис и действие:

заменяют в строке u первое вхождение регулярного выражения tна строку s. Вызов с двумя аргументами означает, что эта операция применяется к текущей записи $0.
— аналогична sub, но заменяются все вхожденияt.
— целочисленная функция, возвращающая в качестве значения длину строки s.
возвращают в качестве значения подстроку строкиs, начинающуюся с -го символа и имеющую символов. Если n отстуствует, считается.
проверяет, содержит ли строка s регулярное выражение t. Если s содержит t, то match(s,t) указывает на начало первого вхождения t в s. Если s не содержит t, то match(s,t) = 0.
целочисленная функция, возвращающая в качестве значения длину строки s.
проверяет, содержит ли строка s строку t. Если s содержит t, то index(s,t) указывает на начало первого вхождения t в s. Если s не содержит t, то index(s,t) = 0.
переводят строку s в верхний (нижний) регистры.

Функции, определяемые программистом

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

function FunctionName(a, b, ..., z)	{	... тело функции ...	}

Относительно имени функции и имен переменных выполняются обычные соглашения о допустимых идентификаторах в awk.

Тело функции представляет собой набор awk-команд, применяемых к списку параметров заголовка функции. Функция может быть »реккурсивной», вызывая самое себя. Количество аргументов в фактическом вызове функции может отличаться от количества аргументов в описании. »Лишние» переменные получают в качестве значений пустую строку"". При вызове функции в awk-программе не должно быть никаких символов ( в том числе и пробельных ) между именем функции и списком аргументов в скобках.

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

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

Переменные

Переменные языка awk могут быть разделены на два класса: встроенные в язык и определяемые программистом. Первые из них имеют фиксированные имена и специальным образом влияют на работу awk. Вторые используются традиционным образом для хранения и использования каких-либо промежуточных результатов.

Встроенные переменные

В последующей таблице приведены встроенные переменные ряда диалектов awk

.

Каноническое множество
FILENAME имя файла, обрабатываемого awk в настоящий момент
FS разделитель полей в записи
NF количество полей в текущей записи
NR номер текущуй записи
OFS разделитель полей при выводе
ORS рпзделитель записей при выводе
RS разделитель записей
$0 адресует всю запись целиком
$n адресует -ое поле в записи
gawk
ARGV массив аргументов командной строки
ARGC количесвто аргументов командной строки
CONVFMT формат внутреннего преобразования »число» »строка»
ENVIRON массив переменных среды
FNR номер записи в текущем файле
IGNORECASE если эта переменная непуста, то все сравнения awk проводит игнорируя разницу ммежду буквами в верхнем и нижнем регистрах
OFMT формат вывода для чисел
RSTART положение первого совпадения, найденого командой match
RLENGTH длина совпадения, найденого командой match
SUBSEP символ-разделитель для индексов массивов

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

Переменные, определяемые программистом

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

Переменные, используемые в программах awk, не требуют предварительного декларирования и их тип определяется контекстом использования. Переменная box может быть проинициализирована строкой "4":

	box = "4"

затем с ней можно выполнить арифметическое действие

	box = box*4

и затем строковую операцию ( например, конкатенацию )

	box = box " boxes of candies"

в результате чего переменная box примет значение "16 boxes of candies".

Преобразование из строкового в числовой тип и обратно происходит прозрачным для пользователя образом. Повлиять на это преобразование можно изменив значение встроенной переменнойCONVFMT, которая по умолчанию имеет значение "%.6g". Результат преобразования числа в строку эквивалентен использованию функции sprintf c переменной CONVFMT, определяющей формат преобразования.

При переводе строки в число awk проявляет досточно интеллекта для того, чтобы распознать "100", "1e2", "100fix" как число 100. При переводе в числовую форму строк типа "Вася" возвращается нулевое значение.

Если по каким-либо причинам необходимо форсировано перевести переменную или выражение из числовой формы в строковую, рекомендуется конкатенировать ее с пустой строкой "". Если необходим перевод из строковой в числовую форму, можно прибавить 0.

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

 

Вызов awk

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

awk [опции] программа файл данных

где программа может быть либо непосредственно текстом awk-программы (в одинарных кавычках), либо ссылкой вида -f file на файл file, содержащий awk-программу. Первый вариант применяется обычно для коротких awk-программ, второй — для сложных awk-текстов, библиотек функций и пр. Используя опцию source, можно смешивать эти два способа представления awk-программ.

Файл данный представляет собой тот файл, к которому применяется awk-программа. Если такой файл отсутствует, по awk-программа применяется к потоку стандартного ввода. Это позволяет применять awk в конвейерах.

Опиции для awk задаются в POSIX-стиле буквой, перед которой располагается знак минус (-). Счастливые пользователи gawk могут использовать »длиные» имена для опций в GNU-стиле, перед которыми необходимо разместить два минуса (-). Вызывая gawk, можно вперемешку использовать длиные и короткие формы опций.

Программа awk понимает в основном следующие опции:

\( \begin{array}{l} \mbox{\tt -F FS}\\ \mbox{\tt --field-separator=FS} \end{array}\) Эта опция устанавливает разделитель полей в записи равный FS.
\( \begin{array}{l} \mbox{\tt -f file}\\ \mbox{\tt --file=file} \end{array}\) указывает на то, что awk-программа находится в файле file
\( \begin{array}{l} \mbox{\tt -v VAR=VAL}\\ \mbox{\tt --assign=VAR=VAL} \end{array}\) присваивает переменной VAR значение VAL. Присвоение выполняется перед началом работы awk-программы.
\( \begin{array}{l} \mbox{\tt -W source=file}\\ \mbox{\tt --source file} \end{array}\) Так же как и f-опция, указывает на то, что awk-программа ( или часть ее ) находится в файле file. Позволяет использовать комбинацию ввода программы через командную строку и из заранее подготовленного файла.
\( \begin{array}{l} \mbox{\tt -W version}\\ \mbox{\tt --version} \end{array}\) Сообщает версию awk(gawk).
-c заставляет »gawk» работать как »awk».
- обозначает конец опций. Далее »-» не обозначает начало опции. Эта опция дает возможность работать с файлами, имена которых начинаются на дефис(-).

Снова отметим, что ваш локальный вариант awk может иметь и другой набор опций, с которыми лучше ознакомиться по руководству. Здесь приведены лишь наиболее употребительные.

Простейшие полезные программки

  • 	{ max = NF > max ? NF : max }
    END 	{ print max }
    

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

  • length($0) < 64
    
    

    Эта ультракороткая программа печатает все строки короче 64 символов. В частности она может помочь восстановить испорченый uuencode-ированый файл, потерявший в процессе передачи хвостовые пробелы в некоторых строках.

    Область действия здесь пуста и поэтому по умолчаниюю производится печать записи.

  • NF > 0
    

    Эта программа фактически удаляет все пустые строки из файла.

  • 	{ if (NF > 0) print }
    

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

  • BEGIN { for (i = 1; i <= 10; i++) print int(101 * rand()) }
    

    Эта программа печатает 10 целых случайных чисел из интервала от нуля до 100.

  • ls -l | awk '{ x += $4 } ; END { print "total bytes: " x }
    

    Эта программа подсчитывает количество байтов в файлах данной директории.

  • expand FILE | awk '{ x = x < length() ? length() : x }
       END { print "maximum line length is " x }''
    

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

  • BEGIN { FS = ":" }
    { print $1 | "sort" }
    

    Эта программа выделяет из файла /etc/passwd с регистрационной информацией имена пользователей и печатает их в алфавитном порядке.

  • { nlines++ }
    END { print nlines }
    

    Подсчет строк в файле.

  • END { print NR }
    

    Также подсчет строк в файле,но уже средствами awk.

  • { print NR, $0 }
    

    Эта программа нумерут сроки в файле.

Где растет awk?

Наиболее близко awk связан с операционной системой UNIX и, как правило, входит во все ее поставки. Более того, он зачастую используется в инсталляционных программах, так что UNIX-программисты воспринимают его как неотемлимый элемент среды UNIX

.

Основным местом хранения awk является депозитарий GNU-программного обеспечения http://www.gnu.org, через который можно выйти на многочисленные зеркала. Версию для DOS/WINDOWS можно найти на сайте www.simtel.net и его зеркалах.

Упражнения

Эти упражнения позволят вам удостовериться в своем мастерстве awk-программирования.

  1. Написать фильтр для объединения каждой нечетной строки файла с последующей (четной)
  2. Написать программу, которая бы выводила символы строки-аргумента в обратном порядке.
  3. Написать программу, которая бы выводила бы на русском языке числа до сотен миллионов.
  4. Написать программу, которая бы решала линейные уравнения вида:

        27*x = 43

     

Bibliography

 

1
Керниган Б.В., Пайк Р. UNIX— универсальная среда программирования: Пер. с англ.; Предисл. М.И. Белякова.— М.: Финансы и статистика, 1992.— 304 с.

Источник: http://kpmit.wl.dvgu.ru/library/nurminski_gawk/gawk.html