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

       

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


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

cut -b список [-n] [файл ...] cut -c список [файл ...] cut -f список [-d разделитель] [-s] [файл ...]

используется для выборки байт (опция -b), символов (-c) либо ограниченных разделителями полей (опция -f) с заданными списком номерами из строк исходных файлов, их конкатенации и выдачи на стандартный вывод. Если применить терминологию реляционных баз данных, cut выполняет операцию проекции отношения.

Список, являющийся аргументом опций -b, -c и -f, задается как последовательность разделенных запятыми или пробелами положительных чисел или диапазонов (с естественными умолчаниями, когда границы опущены). Опция -d определяет разделитель полей (по умолчанию это символ табуляции), -n предписывает не разрывать (многобайтные) символы, опция -s в сочетании с -f подавляет вывод строк, в которых не оказалось символов-разделителей (по умолчанию такие строки копируются на стандартный вывод без изменений).

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

cut -d : -f 1,3 /etc/passwd

Листинг 6.40. Пример использования служебной программы cut. (html, txt)

root:0 bin:1 daemon:2 adm:3 lp:4 sync:5 . . .

Листинг 6.41. Начальный фрагмент возможного результата работы служебной программы cut. (html, txt)

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

paste [-s] [-d список] файл ...

в терминологии реляционных баз данных осуществляет горизонтальное соединение, конкатенируя соответственные строки исходных файлов и помещая результат на стандартный вывод. При наличии опции -s конкатенируются строки каждого из исходных файлов. Во всех случаях строки склеиваются посредством символа табуляции (по умолчанию) или символов из списка - аргумента опции -d. Список этих символов рассматривается как кольцевой, т. е. будучи исчерпан, он используется повторно. Сочетание \0 в нем трактуется как пустая цепочка, а не как нулевой символ.

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

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

ls | paste - - - -



Листинг 6.42. Пример использования служебной программы paste. (html, txt)

Для попарного слияния последовательных строк файла целесообразно "сыграть" на том, что список разделителей - кольцевой (см. пример 6.43).

paste -s -d "\0\n" f.txt

Листинг 6.43. Пример использования служебной программы paste с кольцевым списком разделителей. (html, txt)

Если файл не подпадает под определение текстового из-за чрезмерно длинных строк, утилитой cut можно выделить начальные байты, поместив "хвосты" строк в другой файл. В дальнейшем из двух полученных файлов с помощью служебной программы paste можно воссоздать исходный (см. пример 6.44).

cut -b 1-80 -n f > f1.txt cut -b 81- -n f > f2 . . . paste -d '\0' f1.txt f2 > f3

Листинг 6.44. Пример использования служебных программ cut и paste. (html, txt)



Подразумеваемым разделителем при выводе является пробел.

Допустимы следующие опции.

-a номер_файла

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

-e цепочка

Заменить пустые поля вывода из списка опции -o заданной цепочкой символов.

-o список

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

-t символ

Использовать символ в качестве разделителя. Каждое вхождение символа в строку значимо. Указанный символ используется как разделитель и при вводе, и при выводе.

-v номер_файла

Вместо подразумеваемого вывода выдавать только непарные строки из файла с указанным номером (1 или 2).

-1 номер_поля

Производить соединение по полю   файла1 с заданным номером.

-2 номер_поля

Производить соединение по полю   файла2 с заданным номером.

Рассмотрим примеры. Командная строка (см. пример 6.45) выполняет соединение баз данных пользователей и групп, отсортированных в порядке возрастания идентификаторов групп. На стандартный вывод поступают входные имена, имена групп и основные каталоги (см. пример 6.46).

join -1 4 -2 3 -o 1.1,2.1,1.6 -t : passwd.sorted group.sorted

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

halt:root:/sbin operator:root:/root root:root:/root shutdown:root:/sbin sync:root:/sbin bin:bin:/bin daemon:daemon:/sbin . . .

Листинг 6.46. Начальный фрагмент возможного результата работы служебной программы join.

Пусть имеется два упорядоченных по алфавиту справочника: номера телефонов и адреса электронной почты (см. пример 6.47). Предполагается, что в качестве разделителя полей применяется символ табуляции. Тогда командная строка, показанная в пример 6.48, позволит получить объединенный справочник (см. пример 6.49).

Имя Номер телефона Иван 123-4567 Петр 123-5678 Яков 123-6789

Имя Адрес электронной почты Иван ivan123@mail.ru Олег oleg@yahoo.com Яков yak@yandex.ru

Листинг 6.47. Возможное содержимое двух справочников с информацией о телефонных номерах и об адресах электронной почты.

join -t '<tab>' -a 1 -a 2 -e '---------' -o 0,1.2,2.2 phone.txt email.txt

Листинг 6.48. Еще один пример использования служебной программы join.

Имя Номер телефона Адрес электронной почты Иван 123-45-67 ivan123@mail.ru Олег --------- oleg@yahoo.com Петр 123-56-78 --------- Яков 123-67-89 yak@yandex.ru

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

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


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