Программирование в стандарте POSIX

       

Простейшие средства обработки текстовых файлов


Согласно определению, данному в стандарте POSIX-2001, текстовым называется файл, символы которого объединены в строки длиной не более {LINE_MAX}, не содержащие нулевого символа.

Вероятно, простейшей операцией с файлами (не обязательно текстовыми) является их выдача на стандартный вывод, что обеспечивается посредством утилиты

cat [-u] [файл ...]

Несмотря на внешнюю простоту, применение служебной программы cat сопряжено с рядом тонкостей. Во-первых, опция -u предписывает передавать на стандартный вывод байты из входных файлов без задержек, это означает, в частности, отмену буферизации стандартного вывода. Во-вторых, если не указаны исходные файлы или в качестве аргумента задан знак минус, используется стандартный ввод. Минус может фигурировать в командной строке несколько раз, стандартный ввод не закрывается и не переоткрывается. Например, допустимы команды, показанные в пример 6.1, причем первая обеспечит ввод двух интерактивных вставок, а вторая эквивалентна третьей (читателю предлагается самостоятельно объяснить данный факт).

cat f1.txt - f2.txt - f3.txt cat g1.txt - g2.txt - g3.txt < input.txt cat g1.txt - g2.txt /dev/null g3.txt < input.txt cat f1.txt f2.txt > f1.txt

Листинг 6.1. Пример использования утилиты cat. (html, txt)

В-третьих, нужно учитывать особенности перенаправления вывода командным интерпретатором shell. В общем случае утилита cat выдает результат конкатенации содержимого файлов-аргументов, но выполнение четвертой команды, показанной в пример 6.1, приведет к утрате содержимого файла f1.txt.

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

more [опция ...] [файл ...]

Она разбивает вывод на страницы (экраны) и выдает их по явному указанию пользователя (например, по нажатию клавиши пробела).

Программа more - довольно мощный просмотрщик файлов со своей системой команд, которую мы, однако, описывать не будем. Отметим лишь возможности поиска и перемещения по файлам. Трактовка аргументов аналогична cat, а из опций выделим три.


-n число

Задает число строк, выдаваемых на экран.

-p команды more

Команды more выполняются после входа в очередной файл и вывода его первого экрана. Это может быть, к примеру, команда поиска.



-s

Сжимать последовательные пустые строки в одну.

Утилита more часто используется как заключительное звено конвейеров для удобного просмотра результатов.

Для просмотра нетекстовых файлов рекомендуется служебная программа

od [опция ...] [файл ...]

Она выдает на стандартный вывод содержимое исходных файлов в формате, заданном пользователем, а также в виде блоков, каждый из которых в простейшем (и наиболее употребительном) случае состоит из шестнадцати байт и занимает при выводе одну строку. В начале подобной строки располагается смещение блока от начала файла, затем следует содержимое блока. С помощью аргумента опции -A можно задать основание системы счисления для смещений (d - десятичное, o - восьмеричное, x - шестнадцатеричное, n - не выдавать смещение). Формат выдачи содержимого определяется аргументом опции -t. Помимо перечисленных типов могут быть заданы a (именованные символы), c (символы), f (вещественные числа), u (беззнаковые десятичные). За спецификациями d, f, o, u и x может следовать десятичное число - количество байт в одном значении заданного типа; за спецификацией f - символы F, D или L, указывающие тип вещественных чисел (float, double или long double, соответственно), а за спецификациями d, o, u, x - спецификаторы целочисленного типа C (char), S (short), I(int) или L (long).

Рассмотрим пример. Пусть файл ascii.tab содержит байты от

od -A x -t a ascii.tab

Листинг 6.2. Пример использования утилиты od. (html, txt)

Листинг 6.3. Возможный результат использования утилиты od. (html, txt)

Полезная возможность - взглянуть на начало файла, чтобы понять, нуждается ли он в более детальном изучении. Эта возможность реализуется служебной программой head:

head [-n число] [файл ...]

Утилита head копирует на стандартный вывод указанное число (по умолчанию - 10) начальных строк исходных файлов (или весь файл, если он слишком короткий).



-n число

Задает число строк, выдаваемых на экран.

-p команды more

Команды more выполняются после входа в очередной файл и вывода его первого экрана. Это может быть, к примеру, команда поиска.

-s

Сжимать последовательные пустые строки в одну.

Утилита more часто используется как заключительное звено конвейеров для удобного просмотра результатов.

Для просмотра нетекстовых файлов рекомендуется служебная программа

od [опция ...] [файл ...]

Она выдает на стандартный вывод содержимое исходных файлов в формате, заданном пользователем, а также в виде блоков, каждый из которых в простейшем (и наиболее употребительном) случае состоит из шестнадцати байт и занимает при выводе одну строку. В начале подобной строки располагается смещение блока от начала файла, затем следует содержимое блока. С помощью аргумента опции -A можно задать основание системы счисления для смещений (d - десятичное, o - восьмеричное, x - шестнадцатеричное, n - не выдавать смещение). Формат выдачи содержимого определяется аргументом опции -t. Помимо перечисленных типов могут быть заданы a (именованные символы), c (символы), f (вещественные числа), u (беззнаковые десятичные). За спецификациями d, f, o, u и x может следовать десятичное число - количество байт в одном значении заданного типа; за спецификацией f - символы F, D или L, указывающие тип вещественных чисел (float, double или long double, соответственно), а за спецификациями d, o, u, x - спецификаторы целочисленного типа C (char), S (short), I(int) или L (long).

Рассмотрим пример. Пусть файл ascii.tab содержит байты от

od -A x -t a ascii.tab

Листинг 6.2. Пример использования утилиты od.

000000 nul soh stx etx eot enq ack bel bs ht nl vt ff cr so si 000010 dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us 000020 sp ! " # $ % & ' ( ) * + , - . / 000030 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 000040 @ A B C D E F G H I J K L M N O 000050 P Q R S T U V W X Y Z [ \ ] ^ _ 000060 ` a b c d e f g h i j k l m n o 000070 p q r s t u v w x y z { | } ~ del 000080



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

Утилита pr обрабатывает следующие аргументы командной строки.

+номер_страницы

Начать вывод со страницы с заданным номером (по умолчанию с первой).

-число_столбцов

Вывод в заданное число столбцов (по умолчанию в один). При выводе в несколько столбцов автоматически действуют опции -e и -i. Этот аргумент несовместим с опцией -m.

-a

Выдача в несколько столбцов с упорядочением по строкам. Например, если заказана печать в два столбца, первая исходная строка попадает в первый столбец, вторая - во второй, третья - снова в первый и т.п.

-d

Выдача через строку.

-e[символ][число]

Установка табуляции через заданное число позиций, начиная с первой. Символы табуляции во входном файле развертываются в соответствующее количество пробелов. Если задан любой нецифровой символ, он трактуется как символ табуляции во входном файле.

-F

Применять символы перехода к новой странице (по умолчанию переход на новую страницу осуществляется при помощи последовательности переводов строк).

-h заголовок

Использовать заданный заголовок (по умолчанию в качестве заголовка выступает имя исходного файла).

-i[символ][число]

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

-l число_строк

Установка длины страницы (по умолчанию 66 строк).

-m

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

-n[символ][ширина]

Производится нумерация строк. Под номер отводится поле заданной ширины (по умолчанию - 5). Если задан любой нецифровой символ, то он присоединяется к номеру строки, отделяя ее от последующего текста (подразумеваемым значением является символ табуляции).



Служебная программа sort

sort [-m] [-o выходной_файл] [-bdfinru] [-t символ] [-k определение_ключа] ... [файл ...]

sort -c [-bdfinru] [-t символ] [-k определение_ключа] [файл]

в зависимости от заданных опций выполняет одно из трех возможных действий:



  • сортировку строк всех исходных файлов с записью результата в выходной файл;


  • слияние всех исходных (предварительно отсортированных) файлов с записью результата в выходной файл;
  • проверку того, что единственный исходный файл действительно отсортирован.


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

Следующие опции управляют порядком работы утилиты sort.

-c

Проверить, является ли (единственный) исходный файл уже отсортированным. В выходной файл ничего не записывается, результат работы определяется по коду завершения (0 - успешное завершение, 1 - данные в файле не упорядочены должным образом, больше единицы - зафиксирована ошибка).

-m

Слияние исходных файлов, которые предполагаются отсортированными.

-o выходной_файл

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

-u

Опция уникальности: из всех совпадающих строк выводить только одну, при наличии опции -c контролировать отсутствие строк с совпадающими ключами сортировки.

Следующие опции изменяют подразумеваемый способ сравнения. Если они употреблены независимо от определения ключей сортировки, то диктуемые ими правила действуют глобально, на все ключи.

-d

"Словарный" порядок: при сравнении являются значимыми только буквы, цифры и пробельные символы.

-f

При сравнении преобразовывать малые буквы в большие.

-i

При сравнении игнорировать непечатные символы.

-n

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



Возможный результат приведен в пример 6.10.

12.05.2000 17:30 200 125 120 15.05.2000 17:00 130 80 70 17.05.2000 10:30 150 90 70 17.05.2000 21:45 154 99 74 19.05.2000 10:05 158 83 89 21.05.2000 21:00 161 104 64 22.05.2000 21:00 147 104 69 . . .

Листинг 6.8. Пример исходных данных для служебной программы sort.

sort -r -k 3,3 pp.txt

Листинг 6.9. Пример использования служебной программы sort.

12.05.2000 17:30 200 125 120 18.11.2000 19:30 172 107 68 04.07.2002 09:00 170 98 85 30.10.2001 13:00 168 94 88 27.12.2000 20:30 166 98 69 23.05.2002 10:00 166 104 56 22.05.2002 10:00 166 103 57 23.10.2001 11:00 165 88 88 . . .

Листинг 6.10. Возможный результат работы служебной программы sort.

Если ключи сортировки равны, строки упорядочиваются с учетом всех байт. В рассматриваемом примере это не очень удобно, поскольку они начинаются с номера дня в месяце. Более естественно либо расширить ключ сортировки путем охвата полей нижнего давления и пульса, либо сделать эти поля дополнительными ключами. Оба варианта показаны в пример 6.11, а результат сортировки - в пример 6.12. Отметим, что второй вариант предпочтительнее, поскольку он устойчив к ошибкам выравнивания столбцов.

# Первый вариант - ключ сортировки покрывает # несколько полей sort -r -k 3,5 pp.txt # Второй вариант - используется несколько # ключей сортировки # sort -n -r -k 3,3 -k 4,4 -k 5,5 pp.txt

Листинг 6.11. Два варианта использования служебной программы sort.

12.05.2000 17:30 200 125 120 18.11.2000 19:30 172 107 68 04.07.2002 09:00 170 98 85 30.10.2001 13:00 168 94 88 23.05.2002 10:00 166 104 56 22.05.2002 10:00 166 103 57 27.12.2000 20:30 166 98 69 23.10.2001 11:00 165 88 88 . . .

Листинг 6.12. Результат работы служебной программы sort с несколькими ключами сортировки.

Предположим теперь, что данные о давлении и пульсе разбиты по годам и в уже отсортированном виде хранятся в файлах pp2000.sorted, pp2001.sorted и т.д. Для их слияния можно воспользоваться командной строкой или циклом из пример 6.13. Опять-таки второй вариант предпочтительнее по причине его устойчивости к количеству исходных файлов.



Игнорировать пробельные символы в конце строк; остальные цепочки пробельных символов считать равными.

-c

Производить вывод в формате, обеспечивающем три строки контекста.

-C число

Производить вывод в формате, обеспечивающем заданное число строк контекста.

-e

Производить вывод в формате, пригодном для подачи на вход редактора ed и преобразования файла1 в файл2.

-f

Производить вывод в альтернативном формате, напоминающем -e, но в обратном порядке и не предназначенном для подачи на вход редактора ed.

-r

Если файл1 и файл2 представляют собой каталоги, применять утилиту diff рекурсивно к одноименным и однотипным обычным файлам и каталогам. Если только один из файлов является каталогом, в нем сравнивается "тезка" другого исходного файла.

В качестве примера использования служебной программы diff сравним две версии бинарных утилит (см. пример 6.18). Начальный фрагмент результата показан в пример 6.19. Видно, что различия, по сути, сводятся к добавлению новых файлов.

diff -r binutils-2_14 binutils-2_14-branch

Листинг 6.18. Пример использования служебной программы diff.

diff -r binutils-2_14/bfd/version.h binutils-2_14-branch/bfd/version.h 1c1 < #define BFD_VERSION_DATE 20030612 --- > #define BFD_VERSION_DATE 20031007 Only in binutils-2_14-branch/binutils: ChangeLog Only in binutils-2_14-branch/binutils: arlex.c Only in binutils-2_14-branch/binutils: deflex.c Only in binutils-2_14-branch/binutils: rclex.c Only in binutils-2_14-branch/binutils: syslex.c Only in binutils-2_14-branch: config.guess Only in binutils-2_14-branch/gas: ChangeLog Only in binutils-2_14-branch/gas/config: tc-ns32k.c Only in binutils-2_14-branch/gas: configure Only in binutils-2_14-branch/gas: configure.in Only in binutils-2_14-branch/gas: itbl-lex.c . . .

Листинг 6.19. Фрагмент возможного результата работы служебной программы diff.

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


Содержание раздела