Главная > Операционные системы > UNIX
| 7.11. Продемонстрировать знакомство с оболочками используемыми по
умолчанию в системе | |
---|
| Глава 7. Базовые навыки работы в Unix | |
---|
7.11. Продемонстрировать знакомство с оболочками используемыми по
умолчанию в системеОписание:
Кандидат BSDA должен свободно пользоваться оболочками
sh(1), csh(1) или
tcsh(1). Кандидат должен уметь изменять
поведение обеих оболочек временно или постоянно, включая:
предотвращать уничтожение существующих файлов, использовать
историю команд, определять псевдонимы команд для экономии времени
в командной строке. Кандидат должен знать как временно отменить
псевдоним.
Практика:
sh(1), csh(1) и tcsh(1), включая ! ,
!! , $ , 0 ,
h , t , r ,
p , \ .
Комментарий
В системах BSD поставляется две оболочки, наличие которых
требуется стандартом POSIX:
sh(1) и csh(1). Первая
традичионно используется для написания сценариев. Вторая больше
приспособлена для работы в интерактивном режиме. Конечно ничто не
мешает вам установить у себя bash(1) или
другую, более или менее «продвинутую» оболочку, однако в
нашем курсе мы изучаем только штатные средства BSD, и на то есть
свои основания (см. Раздел 7.7.2, «Почему sh(1)?»).
Поскольку данный раздел посвящён интерактивной работе с
оболочками, мы будем описывать в нём почти исключительно
csh(1). Полное описание данной оболочки, на
русском языке, доступно здесь: [url://csh-1998].
С другой стороны, я отдаю себе полный отчёт в том, насколько
популярна оболочка bash(1) среди системных
администраторов, поэтому иногда буду делать реверансы в её сторону
в стиле «... а в bash(1) тоже есть
подобная функция, она делатся так: ...». Кроме того, в случае
если некая упоминаемая возможность есть и в
bash(1) и в sh(1) я буду
делать реверансы в пользу sh(1), хотя последний
крайне неудачен с точки зрения интерактивной работы.
| Важно |
---|
csh(1) по умолчанию является оболочкой
пользователя root. Никогда не меняйте её на
bash(1) или любую другую оболочку из иерархии
/usr/local ! От пользователя root требуются
некоторые действия в критические моменты жизнедеятельности системы,
когда иерархия /usr несмонтирована. Поэтому
уметь работать в csh(1) может быть жизненно
важно.
|
7.11.1. Предотвращение уничтожения существующих файлов
Для этой цели в оболочках существует режим
«noclobber». В csh(1) он включается
путём задания переменной окружения noclobber .
% touch test
% set noclobber=1
% echo hello > test
test: Файл существует.
% unset noclobber
% echo hello > test
В sh(1) этот режим можно включить используя
аргумент командной строки -C. Таким образом, можно использовать
shebang #!/bin/sh -C .
7.11.2. Некоторые отличия между sh(1) и csh(1)
Существует ряд отличий между оболочками с точки зрения языка.
Язык csh(1) сделан более C-подобным.
Изменения довольно глубоки, в частности
csh(1) трактует 1 как истину, а 0 как ложь, в
отличие от sh(1), поэтому он преобразует
на лету коды возврата программ 0 к 1, а всё, что больше 0 к нулю.
В csh(1) иной синтаксис написания циклов и
других конструкций, больше типов данных. Так в
csh(1) поддерживаются массивы (массивы
поддерживаются и в bash(1)).
csh(1) поддерживает работу с историей
команд и completion. (К стыду своему не знаю как это будет
по-русски, имеется ввиду явление когда имена файлов
дописываются при нажатии клавиши <TAB>). Ни то, ни
другое не поддерживается в sh(1) (но
поддерживается в bash(1)).
7.11.3. Модификаторы переменных в csh(1)
Если в переменной в csh(1) содержится имя
файла, то с ним можно работать используя различные модификаторы:
% set name=/home/emin/BSDCert/BSDCert.xml
% echo $name
/home/emin/BSDCert/BSDCert.xml
% echo $name:h
/home/emin/BSDCert
% echo $name:t
BSDCert.xml
% echo $name:e
xml
% echo $name:h:h
/home/emin
% set names=(/home/emin/BSDCert/*)
% echo $names
/home/emin/BSDCert/BSDCert.xml /home/emin/BSDCert/Makefile /home/emin/BSDCert/de
fault.css /home/emin/BSDCert/index.shtml /home/emin/BSDCert/macro.vim /home/emin
/BSDCert/single.xsl /home/emin/BSDCert/split.xsl
% echo $names[1]
/home/emin/BSDCert/BSDCert.xml
% echo $names[1]:h
/home/emin/BSDCert
% echo $names[1]:t
BSDCert.xml
% echo $names:h
/home/emin/BSDCert /home/emin/BSDCert/Makefile /home/emin/BSDCert/default.css /h
ome/emin/BSDCert/index.shtml /home/emin/BSDCert/macro.vim /home/emin/BSDCert/sin
gle.xsl /home/emin/BSDCert/split.xsl
% echo $names:gh
/home/emin/BSDCert /home/emin/BSDCert /home/emin/BSDCert /home/emin/BSDCert /hom
e/emin/BSDCert /home/emin/BSDCert /home/emin/BSDCert
% echo $names:gt
BSDCert.xml Makefile default.css index.shtml macro.vim single.xsl split.xsl
% echo $names:ge
xml css shtml vim xsl xsl
|
Следующие модификаторы позволяют отобразить некоторые части
имени файла: путь к файлу, имя файла, расширение файла.
Полный список модификаторов приведён ниже в таблице.
| |
Модификатор можно вызвать несколько раз.
| |
В этой строке мы определили массив,
| |
Мы можем работать с отдельным элементом массива, как с
простой переменной. (В bash(1) элементы
массива нумеруются с нуля, а не с единицы, а ссылки на них
ОБЯЗАНЫ браться в фигурные скобки: echo ${names[0]} . В
csh(1) фигурные скобки необязательны.)
| |
При применении модификатора к массиву, он применяется только
к первому элементу, что непрактично.
| |
Однако, комбинируя модификатор с флагом g
(от global), мы можем применить его ко всем элементам
массива.
|
Похожие фокусы возможны, впрочем, и в sh(1)
(правда в нём нет массивов):
$ name=/home/emin/BSDCert/BSDCert.xml
$ echo $name
/home/emin/BSDCert/BSDCert.xml
$ echo ${name%/*}
/home/emin/BSDCert
$ echo ${name##*/}
BSDCert.xml
$ echo ${name##*.}
xml
Впрочем, последний пример явно потерпит фиаско, если в имени
файла расширения не будет, и, что ещё хуже, если в имени файла
его не будет, а в имени каталога, в котором он находится, оно
будет.
Таблица 7.11. Модификаторы переменных в csh(1) Модификатор | Описание |
---|
h |
Удалить имя файла, сохранив компоненты пути (то есть
удалить в слове текст справа до ближайшего символа /).
От слова head.
| gh |
Применить модификатор h глобально ко всем элементам
массива
| r |
Удалить расширение файла, указанное через точку, и
саму точку
| gr |
Применить модификатор r глобально ко всем элементам
массива
| e |
Удалить имя файла вместе с точкой, сохранив расширение
имени
| ge |
Применить модификатор e глобально ко всем элементам
массива
| t |
Сохранить имя файла, удалив компоненты пути (то есть
удалить текст слева от самого правого символа / и сам
этот символ). От слова «tail».
| gt |
Применить модификатор t глобально ко всем элементам
массива
| q |
Запретить дальнейшую модификацию слова. Слово
заключается в кавычки
| x |
Разбить на слова по разделителям и запретить дальнейшую
модификацию. Результат заключается в кавычки.
|
7.11.4. Работа с историей команд
Для просмотра истории команд служит встроенная команда
history:
% history
1 14:27 set name=/home/emin/BSDCert/BSDCert.xml
2 14:28 echo $name
3 14:28 echo $name:h
4 14:28 echo $name:t
5 14:28 echo $name:e
6 14:28 echo $name:h:h
7 14:29 set names= ( /home/emin/BSDCert/* )
8 14:29 echo $names[1]
9 14:29 echo $names[1]:h
10 14:30 echo $names[1]:t
11 14:30 echo $names:h
12 14:30 echo $names:gh
13 14:30 echo $names:gt
14 14:30 echo $names:ge
При помощи символа ! можно выполнить
некоторые действия из истории, например:
% !1
set name=/home/emin/BSDCert/BSDCert.xml
% !7
set names= ( /home/emin/BSDCert/* )
% !?his?
history
1 14:27 set name=/home/emin/BSDCert/BSDCert.xml
2 14:28 echo $name
3 14:28 echo $name:h
4 14:28 echo $name:t
5 14:28 echo $name:e
6 14:28 echo $name:h:h
7 14:29 set names= ( /home/emin/BSDCert/* )
8 14:29 echo $names[1]
9 14:29 echo $names[1]:h
10 14:30 echo $names[1]:t
11 14:30 echo $names:h
12 14:30 echo $names:gh
13 14:30 echo $names:gt
14 14:30 echo $names:ge
15 15:30 history
16 15:31 set name=/home/emin/BSDCert/BSDCert.xml
17 15:31 set names= ( /home/emin/BSDCert/* )
18 15:31 history
% -2
set names= ( /home/emin/BSDCert/* )
% !!
set names= ( /home/emin/BSDCert/* )
% !e
echo $names:ge
xml css shtml vim xsl xsl
|
На команду можно ссылаться по её номеру,
| |
или содержащемуся в ней шаблону.
| |
Отрицательные номера ведут отсчёт с конца
списка — в данном случае мы вызвали вторую с
конца команду.
| |
Примитив !! эквивалентен
-1 , т.е. выполняет повторно последнее
действие.
| |
выполняется последняя команда начинавшаяся с
e , т.е. echo names:ge
|
Разберём чуть более сложный пример:
% touch abc cba
% cat !!*
cat abc cba
% echo 'aaa\
? bbb\
? ccc' > abc
% echo 'aaa\
? bcb\
? ccc'> cba
% diff !t*
diff abc cba
2c2
< bbb
---
> bcb
% echo !t:0
echo touch
touch
% echo !t:1 !t:2
echo abc cba
abc cba
% echo !?ab?%
echo abc
abc
% echo !t^ !t$
echo abc cba
abc cba
|
Вызвав !! в аргументах мы добились того,
что в аргументы команды cat(1) были
переданы аргументы предыдущей команды (т.е.
touch(1)). Благодара знаку
* были переданы все аргументы.
| |
Мы записали при помощи встроенной команды
echo в новые файлы некоторую
информацию, теперь мы можем применить не команду
cat(1) а команду
diff(1). !t ссылается
на команду начавшуюся с буквы t , т.е.
touch(1), а * , как и
раньше означает подстановку всех аргументов.
| |
На аргументы, впрочем, можно ссылаться по номеру при этом
номер 0 ссылается на первый аргумент (т.е. имя команды),
| |
а номера 1, 2 и т.д. на последующие. Здесь
!t — указание на то, что мы
работаем с командой touch(1), а то, что
идёт после двоеточия — указывает на то, какая
часть команды нас интересует. Т.е. нас интересует первый и
второй аргумент этой команды. Можно ссылаться на диапазоны
намеров, например: echo
!..:2- — все аргументы начиная со
второго; echo
!..:2-5 — аргументы со второго по
пятый; echo !..-2 —
аргументы вплоть до второго. Двоеточием здесь заменена
подходящая случаю ссылка на команду.
| |
Здесь мы сослались на аргумент содержащий в себе текст
«ab », по шаблону. Благодаря
знаку % мы ссылались не на всю команду, а
только на найденный аргумент.
| |
Наконец, символ ^ ссылается на слово
номер 1, а $ на последнее слово.
|
Разрешается не ставить двоеточие перед знаками
* , ^ , $ ,
- и %
В работе с историей команд можно использовать модификаторы.
Некоторые модификаторы были рассмотрены выше, есть и
специфические модификаторы, которые применяются только здесь:
p -
Распечатать новую команду, но не выполнять её
& -
Повторить предыдущую подстановку
s/pattern/subst/ -
Заменить pattern на subst,Символ / можно заменить на
любой, отсутствующий в искомом тексте и в строке
подстановки, если subst пустой, то pattern удаляется.
Пусть после выполнения команды history на экран дисплея
выведено:
% history
1 cat /home/ivanov/file1.c
2 cc pa1.c pa2.c pa3.c pa4.c >& errors &
...
Тогда следующие команды приведут к следующим действиям:
!1:0 !1^:t:r -
Сперва будет подставлено нулевое слово первой строки, т.е.
cat . Затем первое слово первой
строки (/home/ivanov/file1.c ),
к которому будет последовательно применено два
модификатора: :t и :r , в
результате останется file1 .
Итого, получаем команду cat
file1 .
!1:0 !1^:h/document -
Аналогично получаем
cat
/home/ivanov/document .
!1:0 !1^:h:s?ivanov?sidorov?/document cat /home/sidorov/document !1:0 !1^:h:s?ivanov?sidorov?/doc !1^:&:p cat /home/sidorov/doc
/home/sidorov/file1.c . Здесь модификатор
& заставляет повторить предыдущую
замену, а модификатор :p заставляет
просто напечатать результат на экране, вместо того, чтобы
выполнить действие.
!1:0 !2:1-4:gs?pa?ff?:p -
Во второй строке выбираются слова с первого по четвёртое,
и в них во всех, (флаг
g ) делается замена
pa на ff , результат печатается:
cat ff1.c ff2.c ff3.c ff4.c
Существует способ редактирования последней командной строки:
% echo abc cba
abc cba
% ^abc^cba^
echo cba cba
cba cba
Представьте себе, что у вас определён следующий псевдоним:
% alias sp "sort \!* | print"
Теперь команды sp one two и sort one two | print тождественны, так
как в !* будут подставлены аргументы, с
которыми вызвана команда sp .
| | | 7.10. Проверка контрольной суммы файла | | 7.12. Чтение почты на локальной машине |
Главная > Операционные системы > UNIX
|