Упражнение 5.17
Почему команда overwriteне использует сигнал 0 в команде trap, чтобы файлы удалялись при выходе из нее? Подсказка: попробуйте нажать клавишу DEL во время выполнения следующей программы:
trap "echo exiting; exit 1" 0 2
sleep 10
Упражнение 5.18
Добавьте флаг -vк команде replaceдля вывода всех измененных строк на /dev/tty.
Подсказка : s/$left/$right/g $vflag.
Упражнение 5.19
Увеличьте надежность команды replace, чтобы ее выполнение не зависело от символов в строке замены.
Упражнение 5.20
Можно ли использовать replaceдля замены iна indexвсюду в программе? Какие вы внесли бы изменения, чтобы добиться этого?
Упражнение 5.21
Достаточно ли команда replaceэффективна и удобна, чтобы находиться в каталоге /usr/bin? Не лучше ли вводить по мере необходимости подходящие команды редактора sed(да или нет)? Обоснуйте свой ответ.
Упражнение 5.22
( Усложненное .) Команда
$ overwrite файл 'who | sort'
не выполняется. Объясните причину этого и исправьте ее. Подсказка : посмотрите evalв справочном руководстве по sh(1). Как ваше решение повлияет на интерпретацию специальных символов в команде?
5.6 Команда zap: уничтожение процесса по имени
Команда killтолько завершает процесс с указанным номером. Если нужно уничтожить определенный фоновый процесс, обычно приходится выполнить команду ps, чтобы узнать номер процесса, а затем ввести этот номер в качестве аргумента для команды kill. Однако нелепо иметь программу, выдающую номер процесса, который сразу же передается вручную другой программе. Имеет смысл написать программу, скажем zap, для автоматического выполнения такой работы. Здесь, правда, есть одно препятствие: уничтожение процессов опасно, поэтому следует принять меры для обеспечения сохранности нужных процессов. Хорошей защитой всегда служат диалоговое выполнение zap и использование команды pickдля выбора "жертв".
Кратко напомним вам о команде pick: она выдает поочередно свои аргументы, спрашивая ответ у пользователя; если ответ — y, то аргумент выводится (команда pickобсуждается в следующем разделе). В нашем случае pickиспользуется для подтверждения, что процессы, выбранные по имени, — именно те, которые пользователь хочет уничтожить:
$ cat zap
# zap pattern: kill all processes matching pattern
# BUG in this version
PATH=/bin:/usr/bin
case $# in
0) echo 'Usage: zap pattern' 1>&2; exit 1
esac
kill `pick \`ps -ag | grep "$*"\` | awk '{print $1}'`
Обратите внимание на вложенные знаки слабого ударения, защищенные символами обратной дробной черты, awkпрограмма выделяет номер процесса из выходных данных команды ps, выбранной с помощью pick:
$ sleep 1000 &
2216
$ ps -ag
PID TTY TIME CMD
...
2216 0 0:00 sleep 1000
...
$ zap sleep
2216?
0? qЧто происходит?
$
Проблема состоит в том, что выходные данные команды psразбиты на слова, которые воспринимаются и обрабатываются командой pickкак отдельные аргументы вместо того, чтобы обрабатываться сразу по строке. Обычная процедура интерпретатора заключается в разбиении строк на аргументы с границами пробел/не пробел, как показано ниже:
for i in 1 2 3 4 5
В этой программе нужно контролировать процесс разбиения интерпретатором строк на аргументы, чтобы только символ перевода строки разделял соседние "слова".
Внутренняя переменная интерпретатора IFS(internal field separator — внутренний разделитель полей) представляет собой строку символов, которая разделяет слова в списке аргументов, находящихся в знаках слабого ударения или циклах for. Обычно IFSсодержит пробелы, символы табуляции и конца строки, но мы можем заменить ее на что-либо нужное, например просто на символ перевода строки:
$ echo 'echo $#' >nargs
$ cx nargs
$ who
you tty0 Oct 1 05:59
pjw tty2 Oct 1 11:26
$ nargs 'who'
1010 полей, разделенных пробелом и концом строки
$ IFS='
' Только конец строки
$ nargs `who`
2 Две строки, два поля
$
После установки IFSравным символу перевода строки команда zapвыполняется отлично:
$ cat zap
# zap pat: kill all processes matching pat
# final version
Читать дальше
Конец ознакомительного отрывка
Купить книгу