Рассел Сейдж. Приемы профессиональной работы в unix перевод "Tricks of the unix masters" by Russel G

Вид материалаДокументы

Содержание


Переменная среды
Управление временем
Управление делопроизводством
Управление временем
Подобный материал:
1   ...   16   17   18   19   20   21   22   23   ...   45
5 printf ("%s\t%s\t/%s$/\n", $1, FILENAME, $0) }'

$@ | sort -u +0 -1


ПЕРЕМЕННАЯ СРЕДЫ


FILENAME awk Переменная, содержащая имя файла.


ОПИСАНИЕ

ЗАЧЕМ НАМ НУЖЕН ctags?


UNIX создан как среда для разработки программного обеспечения. Она

поддерживает и поощряет модульность исходного кода программы. Модуль-

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

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

перемещаемые модули для последующей их сборки в исполняемый модуль.

Такая философия разработки программного обеспечения может, однако,

породить некоторые проблемы. Главная проблема - попытка получить неко-

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

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

гих каталогах. Нужен инструмент, позволяющий нам, людям, посмотреть на

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

с точки зрения физического размещения. Этот подход чем-то аналогичен

чтению книги в сравнении с чтением компьютерной распечатки. Распечатка

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

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

для поиска специфических пунктов).

Ctags преодолевает этот разрыв, создавая файл специального форма-

та, который распознают редакторы vi и ex. Этот файл содержит "призна-

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

обеспечения автоматического доступа к любой нужной функции, не требую-

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

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

пы файлов с исходным кодом на языке Си. Когда вы объединяете его с ре-

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

и посмотреть тело функции. Это значит также, что вы можете легко копи-

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

работаете.

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

построили инструментальное средство, использующее такое преимущество,

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

на Си (в надежде, что у нас есть подходящие файлы!), отмечать, какой

файл имеет требуемую функцию, входить в этот файл редактором (вручную

вводя все символы имени файла), а затем набирать символы шаблона по-

иска. Это большая работа, которая может занять много времени. Благодаря

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

влеченных из исходного кода, вся эта ручная работа сокращается.

Это сочетание возможностей иллюстрирует то, чему не часто прида-

ется значение: владельцы UNIX всегда настороженно относятся к возмож-

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

таких программах, как vi или ex. Зачастую от 90 до 95 процентов необхо-

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

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

новый инструмент.

Ctags уже существует в виде исполняемого модуля в системе Berkely

(BSD) и в нынешней AT&T System V. Он происходит из системы Berkely, но

поддерживается теперь в System V. Это иллюстрация взаимодействия между

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

идеи друг у друга. Данное конкретное воплощение ctags является команд-

ным файлом утилиты awk, имитирующим исполняемую программу из системы

Berkely, а это значит, что пользователи систем XENIX и предыдущих

версий AT&T могут теперь извлечь пользу от применения ctags. Еще одно

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

модифицировать, чтобы обрабатывать другие особенности языка Си. Такое

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

гостоящей лицензии на исходный код.


ЧТО ДЕЛАЕТ ctags?


Ctags просматривает файлы с исходным кодом на Си, переданные в ко-

мандной строке, и печатает список имен функций в каждом исходном файле.

Имена функций имеют специальный синтаксис и должны быть именно в таком

формате, иначе awk не распознает их как таковые. Эти правила заключа-

ются в том, что имя функции должно находиться в начале строки, состоять

из разрешенных символов и за ним должна следовать левая скобка. Пробелы

в имени функции не допускаются. Вот пример модуля программы на Си, по-

даваемого на рассмотрение командному файлу ctags:


main()

{

}


func1(arg1,arg2)

int arg1,arg2;

{

}


func2(arg1,arg2)int arg1,arg2;

{

}


Результат работы ctags направляется в стандартный вывод (на эк-

ран), поэтому он должен быть перенаправлен, чтобы попасть в файл. Вхо-

дом для ctags является любое число имен файлов. Напомним, что если на

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

рывный поток данных, попадающий в один файл. Если вам нужен выводной

файл для каждого входного файла, то для управления ctags можно приме-

нить такой командный файл с циклом:


for F in *.c

do

ctags $F > $F.tags

done


Выход ctags состоит из трех полей в таком формате:


признак имя_файла шаблон_поиска


Реальный выход для примера программы на Си, приведенного выше, был бы

таким:


main /usr/russ/src/program.c /main()$/

func1 /usr/russ/src/program.c /func1(arg1,arg2)$/

func2 /usr/russ/src/program.c /func2(arg1,arg2)$/


Первое поле является именем признака (которое совпадает с именем

функции). Второе поле - маршрутное имя файла, содержащего данную функ-

цию. Третье поле - шаблон поиска, используемый признаковыми средствами

редактора для доступа к функции внутри файла (более подробно об этом -

позже).

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

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

могли найти интересующую вас функцию? Редактор vi предоставляет много

путей для этого. Первый способ - поместить имя используемого файла

признаков в файл .exrc. (Файл .exrc является аналогом файла .profile

для редактора ex и работает также с редактором vi, что не удивительно,

так как vi построен na ex. Поскольку vi - наиболее популярный редактор

системы UNIX, мы применяем его здесь для наших примеров.) Вы можете

иметь файл .exrc, который выглядит примерно так:

set tags=/usr/russ/mytags

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

зуется данный файл признаков. Другой способ - установить файл признаков

после того, как вы вошли в редактор. Чтобы посмотреть, каким является

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

:set tags

Эта команда печатает файл признаков, о котором она знает. Для из-

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

синтаксис, который был в примере файла .exrc:

:set tags=/usr/russ/mytags

Теперь, когда редактор знает, в каком файле искать признаки, к ко-

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

(т.е. к имени функции). Первый способ - объявить его в командной строке

при вызове редактора. Например:

$ vi -t tag

Если вы уже находитесь в редакторе vi, можете применить такую ко-

манду для поиска признака:

:ta tag

Двоеточие означает, что мы направляемся в ex, чтобы выполнить этот

поиск. Мы просим ex найти указанную строку как признак, который разме-

щается в текущем файле признаков. Когда этот признак найден в файле

признаков, редактор vi редактирует файл с соответствующим именем, кото-

рое он берет из поля 2. Это аналогично команде ":e имя_файла". Когда

новый файл внесен в буфер редактора, последнее поле файла признаков

используется в качестве строки шаблона поиска. Синтаксис точно такой

же, как если бы вы набирали его вручную. Курсор перемещается в позицию

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

интересующую вас функцию.


ВЗАИМОСВЯЗЬ МЕЖДУ ex И vi


Несколько отклоняясь от темы, рассмотрим два файла: /bin/ ex и

/bin/vi. Небольшое исследование обнаруживает, что на самом деле это

один и тот же файл. Мы можем проверить это, посмотрев на их индексные

описатели файлов. Введите такую команду:

$ ls -li `path ex vi`

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


510 -rwx--x--t 5 bin bin 121412 Sep 19 1985 /bin/ex

510 -rwx--x--t 5 bin bin 121412 Sep 19 1985 /bin/vi


Это число и есть индексный описатель файла (inode). Поскольку оба

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

же исполняемый модуль. Каким образом он знает, как вы его вызвали?

Программа смотрит на строку argv[0] и видит, какое имя вы использовали

для вызова файла. Затем редактор устанавливает свой интерфейс в соот-

ветствии с тем, как вы его вызвали.

Обратите внимание, что эта программа имеет пять связей. Как нам

найти все другие имена, которыми можно вызвать vi и ex? Мы можем

использовать команду системы UNIX ncheck. Эта команда воспринимает ин-

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

файла . Примеры таких команд:

$ ncheck -i 510 /dev/root

$ ncheck -i 510

Первый синтаксис указывает команде ncheck искать файлы с inode,

равным 510, только в корневой файловой системе. Ncheck ограничена по-

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

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

файловая система начинается с inode 2 и последовательно наращивается.

Каждая файловая система имеет inode 510, который уникален для каждой

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


dev/root:

510 /bin/edit

510 /bin/ex

510 /bin/vedit

510 /bin/vi

510 /bin/view


Если файловая система не указана, как во втором примере, выполня-

ется поиск по всем файловым системам, смонтированным в настоящее время.

Это не слишком хорошо для нас, поскольку пять связей vi должны нахо-

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

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

никаких файлов редактора нет в каталоге /usr, размещенном во втором

разделе диска от корневой файловой системы.


ПРИМЕРЫ


1. $ ctags *.c

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

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

для каждого файла. Порядок файлов алфавитный, так как указано расшире-

ние файла. Конечно, в большинстве случаев вы захотите перенаправить вы-

ход ctags в файл.


2. $ ctags `Find /usr/src -name "*.c" -print`


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

имена файлов, оканчивающиеся на .c и поместить их в командную строку.

Проблема в том, что если найдено слишком много файлов, командная строка

ctags может переполниться и испортить всю команду. В зависимости от

серьезности переполнения, она может испортить и весь ваш процесс shell.


3. $ find /usr/src -name "*.c" -exec ctags {} \; > tags


Находит все исходные файлы на Си в сегменте дерева /usr/src. Для

каждого подходящего файла запускает программу ctags на этом файле.

Использование такой формы записи предотвращает порчу вашей команды (о

которой только что шла речь), а также запускает ctags для каждого имени

файла. Весь выход помещается в файл tags для последующего использова-

ния.

4. $ find /usr/src -type f -print | sort |

> while read FILE

> do

> ctags $FILE

> done >> tags


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

ет все файлы из каталога /usr/src и печатает их маршрутные имена в

стандартный вывод. Затем они сортируются и поступают по конвейеру в

цикл while. Цикл while используется для обслуживания сколь угодно боль-

шого числа файлов без переполнения буферов. Выход цикла while добавля-

ется к одному файлу - tags. Этот цикл громоздкий и медленный, но он вы-

полняет свою работу.


5. $ find /usr/src -print | ctags


Это неправильный способ использования ctags. Выходом команды find

являются маршрутные имена. Ctags читает стандартный ввод, поскольку в

командной строке нет файлов. Получается, что данные, которые читает

awk, являются маршрутными именами от find, которые не имеют корректных

полей для соответствия шаблонам функций. Никакого сопоставления не про-

исходит.

Аналогичную проблему могла бы вызвать такая командная строка:


find /usr -print | wc -l


Вы могли бы интерпретировать это так: "посчитать, сколько строк

имеется во всех файлах каталога /usr". Но в действительности здесь ска-

зано: "сколько имен файлов имеется в древовидной структуре /usr". Для

подсчета общего количества строк в этих файлах нужен такой синтаксис:

find /usr -exec cat {} \; | wc -l

который гласит: "найти все файлы в /usr, распечатать каждый из

них, затем посчитать, сколько строк в них имеется". Чтобы так же посту-

пить с ctags, нужен такой синтаксис:

find /usr/src -name "*.c" -exec cat {} \; | ctags

В отличие от результата, который мы получили бы в предыдущих при-

мерах:


func1 /usr/russ/src/program.c /func1(arg1,arg2)$/

func2 /usr/russ/src/program.c /func2(arg1,arg2)$/


теперь выход будет выглядеть так:


func1 - /func1(arg1,arg2)$/

func2 - /func2(arg1,arg2)$/


ПОЯСНЕНИЯ


Символы "-" вместо имени файла появляются из-за того, что ctags

читает из стандартного ввода. Awk автоматически присваивает своей внут-

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

строке не было файлов.

Весь командный файл есть программа awk. Входом для командного фай-

ла утилиты awk является $@, что представляет все позиционные параметры.

Каждый параметр считается именем исходного файла на Си. Если никакие

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

входном потоке, но это создает некорректный выход, так как переменная

FILENAME в awk имеет по умолчанию значение "-". Поскольку awk требует

имена файлов, мы должны вызывать ctags с именами файлов, а не переда-

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

предыдущем примере.

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

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

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

лает ctags,- изменяет подразумеваемый разделитель полей утилиты awk с

пробела на левую скобку. Благодаря использованию этого символа в ка-

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

поля: имя функции и остаток строки.

Шаблон поиска утилиты awk соответствует синтаксису имени Си-функ-

ции. Оно может начинаться с символов a-z, A-Z или символа подчеркива-

ния. Далее в имени могут быть любые символы из набора a-z, A-Z, 0-9 и

_. Между именем и скобкой нельзя использовать пробелы. Поиск начинается

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

символов (a-z, A-Z, 0-9), а затем левая скобка.

Когда строка соответствует данному шаблону, генерируется выход с

помощью оператора printf. Первое поле - строка, представленная обозна-

чением $1. В данном случае $1 - это только имя функции, исключая левую

скобку. Печатается символ табуляции, затем следующая строка, которая

является переменной FILENAME из утилиты awk. Эта переменная должна быть

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

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

необходимую для доступа к файлу, содержащему функцию. Печатается еще

одна табуляция, затем строка поиска. Строкой поиска является $0, что

представляет всю строку, с которой работает awk. Строке предшествует

символ , а за строкой следует символ $.

Выход пропускается по конвейеру через sort с той целью, чтобы все

признаки шли в отсортированном порядке. Опции сортировки указывают ути-

лите sort проверять только первое поле и печатать только одно появление

строки, если имеется несколько записей.


МОДИФИКАЦИИ ДЛЯ ctags


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

признаков, можем ли мы применить его для других полезных целей? Мы зна-

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

Сии создать признаки, с помощью которых можно получить доступ к этим

структурам в редакторе. В программах на Си имеются не только имена

функций, но и другие интересные конструкции, например имена структур.

Их можно обслуживать с помощью модифицированной версии ctags.

Единственное, что нам нужно знать,- это официальный синтаксис структуры

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

такой формат:


struct name {

int val1;

char val2;

};


Все, что мы должны сделать,- это заставить awk искать все появле-

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

котором признаком является имя структуры. Этот файл, видимо, будет та-

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

структуры, а не имя функции. Фактически, комбинация утилиты awk, приз-

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

которую вы можете захотеть хранить в файле специального формата, напри-

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

нужно подобрать соответствующие разделители и правильно их использо-

вать.

Мы надеемся, что облегчили сопровождение ваших программ и предло-

жили вам идеи для других способов автоматической обработки документа-

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

соглашения о документации с помощью командных файлов, аналогичных

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

является согласование наших программ извлечения информации (stripf,

stripc, strips) и других программ, которые вы пишете, таким образом,

чтобы они могли читать файл-формирователь (makefile, см. Make(1)) и вы-

давать полную документацию по всем исходным файлам, участвующим в дан-

ном проекте.

* ГЛАВА 5. УПРАВЛЕНИЕ ЛИЧНОЙ ИНФОРМАЦИЕЙ I: *


УПРАВЛЕНИЕ ВРЕМЕНЕМ


И ДЕЛОПРОИЗВОДСТВОМ


УПРАВЛЕНИЕ ВРЕМЕНЕМ


at выполнение задач в указанное время

b порожденный shell фоновых задач

greet своевременное приветствие с терминала

lastlog сообщение времени последней регистрации

timelog учет и статистика сеансов работы

today печать календаря с отмеченной текущей датой


УПРАВЛЕНИЕ ДЕЛОПРОИЗВОДСТВОМ


jargon генератор технических терминов

phone база данных с телефонными номерами

office делопроизводитель


УПРАВЛЕНИЕ ЛИЧНОЙ ИНФОРМАЦИЕЙ I:

УПРАВЛЕНИЕ ВРЕМЕНЕМ


И ДЕЛОПРОИЗВОДСТВОМ


ВВЕДЕНИЕ


Мы уже многое знаем о файлах и о том, как управлять файловой