Брайан Керниган - UNIX — универсальная среда программирования
- Название:UNIX — универсальная среда программирования
- Автор:
- Жанр:
- Издательство:Финансы и статистика
- Год:1992
- Город:Москва
- ISBN:5-289-00253-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Брайан Керниган - UNIX — универсальная среда программирования краткое содержание
В книге американских авторов — разработчиков операционной системы UNIX — блестяще решена проблема автоматизации деятельности программиста, системной поддержки его творчества, выходящей за рамки языков программирования. Профессионалам открыт богатый "встроенный" арсенал системы UNIX. Многочисленными примерами иллюстрировано использование языка управления заданиями shell.
Для программистов-пользователей операционной системы UNIX.
UNIX — универсальная среда программирования - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
file1: file2:
This is This is
a test not a test
of of
your our
skill ability.
and comprehension.
diff
вырабатывает следующее:
$ diff file1 file2
2c2
< a test
---
> not a test
4,6c4,5
< your
< skill
< and comprehension.
---
> our
> ability.
$
Диалог с idiff
может выглядеть так:
$ idiff file1 file2
2c2
Первое различие
< a test
---
> not a test
? >
Пользователь выбрал вторую версию
4,6с4,5
Второе различие
< your
< skill
< and comprehension.
---
> our
> ability.
? <
Пользователь выбрал первую (<) версию
idiff output in file idiff.out
$ cat idiff.out
Выходной поток направляется в этот файл
This is
not a test of
your skill
and comprehension.
$
Если вместо <
или >
выдан ответ е
, idiff
вызывает ed
с двумя группами уже прочитанных строк. Если вторым был ответ е
, буфер редактора выглядел бы следующим образом:
your
skill
and comprehension.
---
our
ability.
Все, что пишется редактором обратно в файл, идет в окончательный выходной поток.
И, наконец, любая команда может быть выполнена внутри idiff
с помощью временного выхода посредством !cmd .
Технически самая трудная часть работы diff
, и она уже выполнена. Таким образом, в задачи idiff
входит разбор выходного потока diff
, открытие, закрытие, чтение и считывание соответствующих файлов в нужное время. Главная функция idiff
поддерживает файлы и запускает процесс diff
:
/* idiff: interactive diff */
#include
#include
char *progname;
#define HUGE 10000 /* large number of lines */
main(argc, argv)
int argc;
char *argv[];
{
FILE *fin, *fout, *f1, *f2, *efopen();
char buf[BUFSIZ], *mktemp();
char *diffout = "idiff.XXXXXX";
progname = argv[0];
if (argc != 3) {
fprintf(stderr, "Usage: idiff file1 file2\n");
exit(1);
}
f1 = efopen(argv[1], "r");
f2 = efopen(argv[2], "r");
fout = efopen("idiff.out", "w");
mktemp(diffout);
sprintf(buf,"diff %s %s >%s", argv[1], argv[2], diffout);
system(buf);
fin = efopen(diffout, "r");
idiff(f1, f2, fin, fout);
unlink(diffout);
printf("%s output in file idiff.out\n", progname);
exit(0);
}
Функция mktemp(3)
создает файл, имя которого гарантированно отличается от имени любого существующего файла. Mktemp
переписывает свой аргумент: шесть символов X
заменяются идентификатором процесса и буквой. Системный вызов unlink(2)
удаляет поименованный файл из файловой системы.
Циклическая обработка изменений, о которых сообщает diff
, выполняется функцией idiff
. Основная идея достаточно проста: печатать порцию выходного потока diff
, пропускать нежелательные данные в одном файле, а затем копировать требуемый вариант из другого файла. В программе есть много утомительных подробностей, так что она оказывается несколько больше, чем нам бы хотелось, но по частям ее довольно легко понять.
idiff(f1, f2, fin, fout) /* process diffs */
FILE *f1, *f2, *fin, *fout;
{
char *tempfile = "idiff.XXXXXX";
char buf[BUFSIZ], buf2[BUFSIZ], *mktemp();
FILE *ft, *efopen();
int cmd, n, from1, to1, from2, to2, nf1, nf2;
mktemp(tempfile);
nf1 = nf2 = 0;
while (fgets(buf, sizeof buf, fin) != NULL) {
parse(buf, &from1, ftto1, &cmd, &from2, &to2);
n = to1-from1 + to2-from2 + 1; /* #lines from diff */
if (cmd == 'c')
n += 2;
else if (cmd == 'a')
from1++;
else if (cmd == 'd')
from2++;
printf("%s", buf);
while (n-- > 0) {
fgets(buf, sizeof buf, fin);
printf("%s", buf);
}
do {
printf("? ");
fflush(stdout);
fgets(buf, sizeof buf, stdin);
switch (buf[0]) {
case '>':
nskip(f1, to1-nf1);
ncopy(f2, to2-nf2, fout);
break;
case '<':
nskip(f2, to2-nf2);
ncopy(f1, to1-nf1, fout);
break;
case 'e':
ncopy(f1, from1-1-nf1, fout);
nskip(f2, from2-1-nf2);
ft = efopen(tempfile, "w");
ncopy(f1, to1+1-from1, ft);
fprintf (ft, "---\n");
ncopy(f2, to2+1-from2, ft);
fclose(ft);
sprintf(buf2, "ed %s", tempfile);
system(buf2);
ft = efopen(tempfile, "r");
ncopy(ft, HUGE, fout);
fclose(ft);
break;
case '!':
system(buf+1);
printf("!\n");
break;
default:
printf("< or > or e or !\n");
break;
}
} while (buf[0]!='<' && buf[0]!='>' && buf[0]!='e');
nf1 = to1;
nf2 = to2;
ncopy(f1, HUGE, fout); /* can fail on very long files */
unlink(tempfile);
}
Функция parse
выполняет рутинную, но тонкую работу по разбору строк, выдаваемых diff
, извлекая четыре номера строки и команду (одну из а
, с
или d
). При этом parse
немного усложняется, так как diff
может выдать либо один номер строки, либо два с той или другой стороны буквы команды:
parse(s, pfrom1, pto1, pcmd, pfrom2, pto2)
char *s;
int *pcmd, *pfrom1, *pto1, *pfrom2, *pto2;
{
#define a2i(p) while (isdigit(*s)) p = 10*(p) + *s++ - '0'
*pfrom1 = *pto1 = *pfrom2 = *pto2 = 0;
a2i(*pfrom1);
if (*s == ',') {
s++;
a2i(*pto1);
} else
*pto1 = *pfrom1;
*pcmd = *s++;
a2i(*pfrom2);
if (*s == ',') {
s++;
a2i(*pto2);
} else
*pto2 = *pfrom2;
}
Макрокоманда a2i
выполняет специальное преобразование из ASCII в целое в тех четырех местах, где она встречается.
Функции nskip
и ncopy
пропускают или копируют указанное число строк из файла:
nskip(fin, n) /* skip n lines of file fin */
FILE *fin;
{
char buf[BUFSIZ];
while (n-- > 0)
fgets(buf, sizeof buf, fin);
}
ncopy(fin, n, fout) /* copy n lines from fin to fout */
FILE *fin, *fout;
{
char buf[BUFSIZ];
while (n-- > 0) {
if (fgets(buf, sizeof buf, fin) == NULL)
return;
fputs(buf, fout);
}
}
Программа idiff
, если ее прервать, оставляет несколько файлов, хранящихся в /tmp
. В следующей главе мы покажем, как перехватывать прерывания, чтобы убрать временные файлы, подобные использованным здесь.
Если критически подойти к zap
и idiff
, то оказывается, что самая трудная работа была уже кем-то сделана ранее. Эти программы только обеспечивают удобное взаимодействие с другой программой, которая обрабатывает нужную информацию. Всегда имеет смысл воспользоваться плодами чужих трудов это позволяет повысить эффективность своей работы.
Добавьте команду q к idiff
: ответ q с автоматически выберет остаток от альтернатив '<'
; q > возьмет все оставшееся от альтернатив '>'
.
Интервал:
Закладка: