Упражнение 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'
10
10 полей, разделенных пробелом и концом строки
$ IFS='
'
Только конец строки
$ nargs `who`
2
Две строки, два поля
$
После установки IFS
равным символу перевода строки команда zap
выполняется отлично:
$ cat zap
# zap pat: kill all processes matching pat
# final version
Читать дальше
Конец ознакомительного отрывка
Купить книгу