Документация по ОС FreeBSD Вторник, 17.06.2025, 10:27
Приветствую Вас Гость | RSS
Меню сайта

Категории каталога
Мои статьи [0]
Установка и настройка [281]
X Window [25]
Man pages [30]
Ports & Packages [26]
cvs [18]
Multimedia [20]
Нововсти в мире Unix [0]
RFC [4]
RFC (Request for Comments, Запрос на комментарии) - серия документов, публикуемая сообществом исследователей и разработчиков, руководствующихся практическими интересами, в которой описывается набор протоколов и обобщается опыт функционирования Интернет.
Безопасность [52]
Работа с железом [58]
Книги по FreeBSD [17]
Сеть [505]
Программирование [40]
FireWall [58]
Темы экзамена BSDA [14]
Официальные темы экзамена BSDA, включая подробноые описания и советы по обучению.

Главная » Статьи » Установка и настройка

Основы ОС UNIX. Учебный курс. Часть 9

Copyleft (no c) - Fuck copyright! 1996-2003 В. Кравчук, OpenXS Initiative, идея, составление, перевод, примеры

Редактор vi

vi (vedit) - экранно-ориентированный текстовый редактор. Он позволяет видеть одновременно целую страницу текста, перемещаться по нему курсором и непосредственно видеть вносимые изменения.

Редактор vi является наследником строкового редактора ex, который, в свою очередь, является расширением базового текстового редактора ed. Тем самым, обеспечивается преемственность средств редактирования и использование эффективного механизма поиска и замены на базе регулярных выражений.

Вызов

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

vi [+строка] [ файл ]

В результате, указанный файл открывается в окне редактора. Если файл не указан, редактируется первоначально пустой буфер (т.е. новый файл, имя которого первоначально не задано).

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

+номер Строка с указанным номером
+ Последняя строка файла
+/re Строка, соответствующая указанному регулярному выражению re

Указанная строка будет находиться в центре экрана (если только файл не меньше, чем размер экрана) и в ее начале будет установлен курсор.

Режимы работы

Редактор vi поддерживает несколько режимов работы:

Командный режим Нормальный и начальный режим. По завершении других режимов происходит возврат в командный режим. Для форсированного перехода в этот режим используется клавиша Esc
Режим ввода В режим ввода входят при задании одной из следующих команд: a A i I o O c C s S R. При этом может набираться произвольный текст. Из этого режима выходят либо по Esc, либо он автоматически прерывается редактором. При этом обычно подается звуковой сигнал.
Режим последней строки Чтение ввода для команды : / ? или !; прекращается нажатием клавиши Enter.

Основные команды

Основные команды редактора vi представлены в табл. 22.

Таблица 22. Сводка основных команд редактора vi

Перемещение курсора
H (Ctrl-h) курсор влево
J (Ctrl-n) курсор вниз
K (Ctrl-p) курсор вверх
L (Space) курсор право
Ctrl-u Переход вверх на половину экрана
Ctrl-d Переход вниз на половину экрана
Ctrl-f На страницу вперед (PageDn)
Ctrl-b На страницу назад (PageUp)
0 Переход в начало текущей строки
$ Переход в конец текущей строки
nG Переход на строку с номером n
Добавление текста
a Добавить текст после курсора
A Добавить текст в конце текущей строки
i Вставить текст перед курсором
I Вставить текст в начале текущей строки
o Образовать новую строку под текущей
O Образовать новую строку над текущей
Изменение текста
~ Изменить регистр символа над курсором
r Замена одного символа
R Замена символов
Удаление текста
x Удаление символа
dd Удаление строки
Ndd Удаление N строк
Поиск и замена
/str Поиск строки str вперед. str может быть регулярным выражением
?/str Поиск строки str назад
n Повторить поиск в том же направлении
N Повторить поиск в обратном направлении
:[range]s/old/new/[g] Заменить old на new в указанном диапазоне строк range. new и old могут быть регулярными выражениями, а range задается аналогично диапазону строк в редакторе ed. Суффикс g означает заменить во всем файле.
Копирование текста
yy Копирование строки в целом
Nyy Копирование N строк
p Вставить из буфера после (курсора, текущей строки)
P Вставить из буфера перед (курсором, текущей строкой)
Выход из редактора
:wq ENTER Запись и выход. Записать текст из буфера в файл и выйти из редактора.
:x ENTER Условная запись и выход. Записать текст из буфера только при наличии изменений и выйти из редактора.
:q! ENTER Закончить редактирование без записи изменений.
Другие команды
! Выполнить одну команду интерпретатора
. Повторить последнюю команду
u Отменить действие последней команды
J Соединить строки
Ctrl-G Показать номер текущей строки

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

Командный интерпретатор

Пользователь ОС UNIX общается с системой через командный интерпретатор (shell). Через него происходит доступ к командам, файловой системе и другим функциям ядра UNIX. Это обычная программа (т.е. не входит в ядро операционной системы UNIX). Ее можно заменить другой или использовать несколько разных версий. Наиболее известны следующие версии:

sh
Классический интерпретатор версии UNIX V7, иначе называемый по фамилии автора Bourne shell.

ksh
Интерпретатор Korn shell, дополняющий классический shell возможностями работы с заданиями пользователя, историей работы и позволяющий редактировать командную строку при помощи команд, аналогичных vi. Является фактически стандартом для POSIX-совместимых систем, в частности, UNIX System V.

csh
Стандартный интерпретатор BSD UNIX и производных от него систем. Отличается улучшенными диалоговыми возможностями, способом присваивания и экспортирования переменных в среду, управляющими конструкциями и рядом других моментов; тоже поддерживает историю и редактирование командной строки. Главное и, по моему мнению, отрицательное его отличие от других интерпретаторов, - это свои управляющие конструкции, не совпадающие с sh.

bash
Свободно распространяемый в виде исходных текстов интерпретатор, называемый "Bourne another shell", объединяющий все лучшее из остальных интерпретаторов с удобными возможностями редактирования командной строки и работы с историей команд. В настоящее время - фактический стандарт.

В рамках этого курса мы будем рассматривать, в основном, средства, не выходящие за пределы возможностей командных интерпретаторов sh и ksh (в классической версии 1988 года).

Структура командной строки

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

<пробел> ::=
<символ пробела> | <символ табуляции>
<имя> ::=
<буква или подчеркивание> {<допустимый символ имени>}
<буква или подчеркивание> ::=
<буква> | _
<допустимый символ имени> ::=
<буква> | <цифра> | _
<параметр> ::=
<имя> | <цифра> | * | @ | # | ? | - | $ | !
<слово> ::=
<не пробел> {<не пробел>}
<простая команда> ::=
<слово> {<пробел> <слово>}

Итак, простая команда - это последовательность слов через пробел. Нажатие клавиши Enter при вводе команды или перевод строки при обработке сценария являются для командного интерпретатора признаком завершения команды. Она обрабатывается и выполняется.

Значением простой команды является ее статус выхода (см. далее) в случае нормального завершения или (восьмеричное) 200+статус при ненормальном завершении.

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

$ who
oracle pts000 Aug 20 10:08
root console Aug 20 09:03
intdbi pts004 Aug 20 12:45
$

Из простых команд строятся более сложные конструкции: конвейеры и списки.

<конвейер> ::=
<команда> {| <команда>}
<список> ::=
<конвейер> {<разделитель> <конвейер>} [<терминатор команды>]
<разделитель> ::=
&& | || | <терминатор команды>
<терминатор команды> ::=
; | &

Конвейер - это последовательность одной или более команд, разделенных |. Стандартный выходной поток каждой команды, кроме последней, соединяется при помощи программного канала со стандартным входным потоком следующей команды. Каждая команда выполняется как отдельный процесс; интерпретатор ожидает окончания последней команды. Статусом выхода конвейера является статус выхода его последней команды. Вот пример простого конвейера:

$ ls | tee save | wc
 15 15 100
$

Список - это последовательность одного или более конвейеров, разделенных ;, &, && или || и, возможно, заканчивающаяся ; или &. Из этих четырех символов, ; и & имеют равный приоритет, который ниже, чем у && и || (эти символы тоже имеют равный приоритет). Точка с запятой (;) вызывает последовательное выполнение предшествующего конвейера (т.е. командный интерпретатор ожидает окончания конвейера перед выполнением любых команд, следующих за точкой с запятой). Амперсанд (&) вызывает асинхронное выполнение предшествующего конвейера (т.е. командный интерпретатор не ожидает окончания работы конвейера). Символ && (||) ведет к тому, что следующий за ним список выполняется только в том случае, когда предыдущий конвейер вернул нулевой (ненулевой) статус выхода. В список может входить произвольное количество переводов строк и точек с запятой, разделяющих команды.

Теперь можно дать общее определение команды:

<команда> ::=
<простая команда> |
<оператор управления> |
<определение функции> |
<список> | (<список>) | { <список>; }

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

Список в фигурных скобках выполняется в текущем командном интерпретаторе, без порождения дополнительного процесса, и замещает образ командного интерпретатора (это аналог системного вызова exec).

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

Рассмотрим пример сложной команды:

bash$ (sleep 5; date) & date
[1] 1148
Wed Aug 20 15:00:11 ???? 1997
bash$ Wed Aug 20 15:00:16 ???? 1997

Фоновый процесс начинается, но сразу "засыпает"; тем временем вторая команда date выдает текущее время, а интерпретатор - приглашение для ввода новой команды. Через пять (примерно, зависит от загрузки системы и т.п.) секунд прекращается выполнение команды sleep и первая команда date выдает новое время.

Метасимволы командного интерпретатора

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

Метасимволы не входят в команды и обрабатываются в несколько проходов до начала выполнения реальных программ.

Таблица 23. Метасимволы командного интерпретатора

Метасимвол Интерпретация
> prog>file - переключить стандартный выходной поток в файл
>> prog>>file - добавить стандартный выходной поток к файлу
< prog - извлечь стандартный входной поток из файла
| p1 | p2 - передать стандартный выходной поток p1 как стандартный входной поток p2
< "Документ здесь": стандартный входной поток задается в последующих строках до строки, состоящей только из символов str. По умолчанию в данных интерпретируются метасимволы \, $ и ``. Если необходимо предотвратить в данных интерпретацию всех метасимволов, необходимо экранировать строку str, предварив обратной косой или взяв в двойные или одиночные кавычки.
* Задает в имени файла любую строку из нуля или более символов
? Задает любой символ в имени файла
[abc] Задает любой символ из [abc] в имени файла, при этом допускаются диапазоны, задаваемые при помощи дефиса -. Если первым символом после [ является !, с этой конструкцией сопоставляется любой символ, не входящий в квадратные скобки.
; Разделитель команд: p1; p2 - выполнить p1, затем p2.
& Выполняет предшествующую команду в фоновом режиме
`...` Инициирует выполнение команд(ы) в ...; `...` заменяется на полученный в результате выполнения стандартный выходной поток
(...) Инициирует выполнение команд(ы) ... в порожденном командном интерпретаторе
$1,$2,...$9 Заменяются аргументами командного файла
$var Значение переменной (ключевого параметра) var в сеансе
${var} Значение var: исключает коллизии в случае конкатенации переменной с последующим текстом
\ \c - использовать непосредственно символ c, \перевод строки - отбрасывается
'...' Непосредственное использование того, что в кавычках
"..." Непосредственное использование, но после того, как будут интерпретированы метасимволы $, `...` и \
# Начало комментария
var=value Присваивает значение value переменной var
p1&&p2 Выполнить p1; в случае успеха выполнить p2
p1||p2 Выполнить p1; в случае неудачи выполнить p2
Примечание

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

Перед выполнением команды каждое слово-аргумент команды просматривается в поисках метасимволов *, ? и [. Если в слове есть один из этих символов, слово рассматривается как шаблон (обратите внимание на синтаксические отличия от шаблонов ed). Такое слово заменяется отсортированными в алфавитном порядке именами файлов, соответствующих шаблону. Если ни одно их имен файлов не соответствует шаблону, слово оставляется без изменений. Символ . в начале имени файла или сразу после /, а также сам символ /, должны сопоставляться явно.

При таком количестве метасимволов интерпретатора необходимо иметь возможность экранировать специальный символ от интерпретации. Для этого можно использовать апострофы, кавычки или обратную косую. При этом кавычки одного вида могут экранировать кавычки другого вида. Обратите внимание, что кавычки "", в отличие от апострофов, не экранируют строку полностью - интерпретатор заглядывает внутрь кавычек в поисках $, `...` и \.

В кавычках могут содержаться переводы строк, пробелы, табуляции, символы ;, &, (, ), |, ^, < и >. Задавая имя файла в кавычках, можно создать файлы с такими нетривиальными символами в именах. Впрочем, делать это не рекомендуется, так как работать с ними будет явно неудобно.

Создание сценариев

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

$ who | wc -l

и для этой цели нужна новая программа nu.

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

$ echo 'who | wc -l' >nu

Интерпретатор является такой же программой, как редактор, who или wc. Раз это программа, ее можно вызвать и переключить ее входной поток. Итак, запускаем интерпретатор с входным потоком, поступающим из файла nu, а не с терминала:

$ who
oracle pts000 Aug 20 10:08
root console Aug 20 09:03
intdbi pts004 Aug 20 12:45
$ cat nu
who | wc -l
$ sh < nu
 3
$

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

$ sh nu

На самом деле, этот вызов отличается, так как входной поток sh остается связанным с терминалом.

Не хотелось бы вводить sh каждый раз, кроме того, это создает различие между командами, написанными на языке shell, и другими выполняемыми файлами. Поэтому, если текстовый файл предназначен для выполнения, то интерпретатор считает, что он состоит из команд (интерпретатор csh требует, чтобы файл начинался с #).

Примечание
Если в первой строке выполняемого текстового файла указано:
 #!/полный_путь_к_программе опции_программы
то данный текстовый файл будет интерпретироваться указанной программой, при вызове которой будут установлены заданные опции. Так можно выполнять, например, программы командного интерпретатора csh, не выходя из sh. Точно так же можно автоматически вызвать и интерпретаторы других языков сценариев, например, Perl.

Все, что вам нужно сделать, это объявить файл nu выполняемым, задав:

$ chmod +x nu

а затем вы можете вызывать его посредством

$ nu

На самом деле, при выполнении команды nu создается новый процесс интерпретатора (порожденный интерпретатор), который и выполняет команды, содержащиеся в nu. Чтобы команда выполнялась в том же интерпретаторе, необходимо поставить перед вызовом команды точку (.). Заметьте, что

$ . nu

выполняется быстрее, чем простой вызов nu.

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

Предположим, необходимо программу cx для установки права доступа к файлу на выполнение, так что

$ cx nu

есть сокращенная запись для

$ chmod +x nu

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

При выполнении командного файла, каждое вхождение $1 заменяется первым аргументом, $2 - вторым и так далее до $9. $0 заменяется именем выполняемой команды. Поэтому, если файл cx содержит строку

chmod +x $1

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

$ cx nu

порожденный интерпретатор заменит $1 первым аргументом команды nu.

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

Как быть, если нужно работать с несколькими аргументами, например, заставить программу cx делать выполняемыми несколько файлов? Можно включить девять аргументов в командный файл (явно можно задавать только девять аргументов, так как конструкция $10 распознается как "первый аргумент, за которым следует 0"):

chmod +x $1 $2 $3 $4 $5 $6 $7 $8 $9

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

Интерпретатор предоставляет специальный параметр $*, который заменяется всеми аргументами команды, независимо от их количества. С учетом этого, правильное определение cx будет таким:

chmod +x $*

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

Таблица 24. Позиционные и специальные параметры командного интерпретатора

Параметр Назначение
$0 Имя выполняемой команды
$1,$2,...$9 Заменяются аргументами командного файла
$# Количество аргументов
$* Все аргументы, передаваемые интерпретатору. "$*" является единым словом, образованным из всех аргументов, объединенных вместе с пробелами.
$@ Аналогично $*. "$@" идентично аргументам: пробелы в аргументах игнорируются, и получается список слов, идентичных исходным аргументам.
$- Флаги, установленные в интерпретаторе.
$? Значение, возвращенное последней выполненной командой (статус выхода).
$$ Номер процесса интерпретатора.
$! Номер процесса последней команды, запущенной асинхронно с помощью &.

Переменные и присваивание

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

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

переменная=значение

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

Присваиваемое значение должно выражаться одним словом, и его следует взять в кавычки, если оно содержит метасимволы, которые не нужно обрабатывать.

Создание (определение) переменной происходит при первом присваивании ей значения. Переменные не нужно явно объявлять до момента их использования. Если переменная не объявлена (не получила значения), при обращении к ней будет получена пустая строка. Все переменные в командном интерпретаторе - строковые, поэтому тип переменной задавать не надо. Некоторые команды интерпретируют строки как числа.

Многие переменные, как, например, PATH, имеют специальное значение для интерпретатора. По традиции, такие переменные называют встроенными и обозначают прописными буквами, а обычные переменные - строчными. Основные встроенные переменные представлены в табл. 25.

Таблица 25. Встроенные переменные командного интерпретатора

Переменная Значение
$HOME Начальный каталог пользователя.
$PATH Путь для поиска выполняемых команд.
$CDPATH Путь поиска для команды cd.
$IFS Список символов, разделяющих слова в аргументах
$MAIL Файл почтового ящика. Командный интерпретатор информирует пользователя о получении почты в указанный файл.
$MAILCHECK Эта переменная определяет, как часто (в секундах) интерпретатор будет проверять поступление почты в файл, определяемый переменной MAIL. По умолчанию принято значение 600 секунд. При установке в 0, интерпретатор будет проверять почту перед каждой выдачей строки-приглашения.
$PS1 Строка-приглашение, по умолчанию принята '$ '
$PS2 Строка-приглашение при продолжении командной строки, по умолчанию принята '> '

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

$ pwd
/home/intdbi/dosapps/doc/book/unix/shell
$ dir=`pwd`
$ cd
$ ln $dir/cx .
...
$ cd $dir
$ pwd
/home/intdbi/dosapps/doc/book/unix/shell

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

Присваивание значения переменной при вызове

Переменные называют ключевыми параметрами, поскольку им можно передавать значение по имени при вызове. Рассмотрим пример:

$ echo 'echo $x' >echox
$ cx echox
$ echo $x
Hello
$ echox
$ x=Hi echox
Hi

По умолчанию ключевые параметры можно передавать только до имени команды. Если установить флаг интерпретатора -k (set -k), то можно будет передавать значения переменным и после имени команды.

Экспортирование переменных в среду

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

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

$ x=Hello 
$ export x 
$ PS1='new$ ' sh 
new$ echo $x
Hello
new$ x='Good Bye'
new$ echo $x
Good Bye
new$ exit
$
$ echo $x
Hello$

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

Для просмотра значений всех переменных среды предназначена команда env.

Категория: Установка и настройка | Добавил: oleg (10.12.2007)
Просмотров: 1052 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа

Beastie

Друзья сайта

Статистика

Онлайн всего: 8
Гостей: 8
Пользователей: 0
links

Copyright MyCorp © 2025