Библиотека сайта rus-linux.net
HuMan: cut
Оригинал: здесь.Автор: Алексей Дмитриев
Дата: 10 декабря 2008
Предисловие
Прежде чем перейти к делу, я должен объяснить, что значит HuMan, и почему я дошел до необходимости изобретать новые слова.HuMan расшифровывается как HumanManual, или, говоря по-русски, ГУманное РУководство. Иначе говоря, руководство, написанное человеком, уже разобравшимся с командой, и для человека, впервые столкнувшегося с ней; то есть написанное по-человечески.
Отныне я буду пересказывать русским языком, со множеством примеров, руководства команд, с применением которых мне удастся разобраться, и публиковать их под одинаковым заголовком. Синтаксис этого заголовка будет такой:
HuMan: <имя команды>
А чем, слышу я возмущенные голоса многочисленных гуру от Линукса и прочих Юниксовидных ОС, обычные маны тебе не хороши? Отвечаю: большую часть манов я лично не понимаю, или не понимаю до конца (наверно я особенно невосприимчив к этому жанру). Я достаточно владею английским языком, чтобы со словарем разобраться практически с любым текстом. Но вот маны написаны зачастую так, что и старина Билл Гейтс в них не разобрался бы (может быть, поэтому он создал Windows, где нет никаких манов).Мне кажется даже, что я понимаю причины и механизм этого явления. Программы пишут программисты, это люди особенного склада, творческие и увлекающиеся. И когда программа написана, ошибки наконец-то выловлены и отлажены, то надоела она уже хуже горькой редьки; к тому же в голове уже зреет новая идея. А тут надо ман писать! Да отпишусь побыстрее, не особенно выбирая слова (зачастую не родного английского языка), кому надо - разберется. К тому же автор программы настолько хорошо ее знает, что многие вещи, ставящие в тупик постороннего, кажутся ему очевидными, и он, в лучшем случае, мимоходом коснется их. В результате получаются неудобопонятные, неграмотно сляпанные руководства, в которых могут разобраться разве что другие программисты. А чтобы дать примеры... нет уж, увольте.
Я не хочу сказать, что таковы все мануалы. Попадаются и понятные, но все же очень много откровенно плохих (то есть по ним очень трудно овладеть программой, которую они описывают). Мне тут могут напомнить про известную рыбку из пруда, но я буду стоять на своем - я не хочу тратить половину дня, чтобы разобраться с опциями простой программы.
Вот не далее как сегодня, я сочинял статью про перенаправления ввода/вывода и программные каналы в Юниксовидных ОС. Дошло дело до команд-фильтров, которые и делают программные каналы и перенаправления столь всемогущими. Стал я приводить список команд-фильтров, дошел до команды cut и тут убедился, что автор статьи, откуда я беру пример, сам не вполне знает команду, о которой пишет. Вот точная цитата из его статьи (не буду раскрывать инкогнито): "Users can also cut based upon "fields" of data by using the -f and (perhaps) the -d options. Refer to man pages for additional details." Перевод: "Пользователи могут также вырезать, пользуясь командой cut, ориентируясь по "полям" данных, применяя опцию -f и (возможно) опцию -d. Детали ищите в манах программы cut". Значит я не одинок! Кто-то еще не смог, или не захотел тратить время на расшифровку китайской грамоты мана.
Что же, нечего делать, полезем в маны. Привожу русский ман этой программы (очень грамотный и почти дословный перевод с английского):
cut
Section: Команда Русский ман (1)
НАЗВАНИЕ
cut - удаляет секции из каждой строки файлов
СИНТАКСИС
cut {-b список-байтов, --bytes=список-байтов} [-n] [--help] [--version] [файл...]
cut {-c список-символов, --characters=список символов} [--help] [--version] [файл...]
cut {-f список полей, --fields=список-полей} [-d разделитель] [-s]
[--delimiter=разделитель] [--only-delimited] [--help] [--version] [файл...]
ОПИСАНИЕ
Это документация не обновлялась долгое время и по этому может оказаться
неточной или неполной. Используйте авторскую документацию в Texinfo.
Эта страница руководства описывает GNU версию программы cut. cut печатает
секции каждой строки каждого входного файла (или стандартного ввода, если
входные файлы не заданы). Имя файла `- ' означает стандартный ввод. Секции,
которые будут напечатаны, определяются заданием опций.
ОПЦИИ
список-байтов, список-символов, и список-полей могут быть одним числом или
несколькими числами, а также диапазонами (два числа разделенных тире) которые
перечисляются через запятую. Первый байт, символ и поле нумеруются 1. Могут
быть заданы неполные диапазоны: `-m ' означает `1-m '; `n- ' означает `n '
через конец строки или следующее поле.
-b, --bytes список-байтов
Печатает только байты в позициях перечисленных в списке-байтов. Табуляции и
backspaces трактуются как любой другой символ; они занимают 1 байт.
-c, --characters список-символов
Печатает только символы в позициях перечисленных в списке-символов. Так же
как и в случае -b табуляции и backspaces трактуются как любой другой символ;
они занимают 1 символ, но интернационализация будет вносить свои изменения.
-f, --fields список-полей
Печатает только поля перечисленные в списке-полей. Поля по умолчанию разделяются
символом TAB.
-d, --delimiter разделитель
Для -f, поля разделяются первым символом, указанным в delim вместо символа TAB.
-n
Не разбивать многобайтные символы (ничего не делать для этого случая)
-s, --only-delimited
Для -f, не печатать строки, которые не содержат символ-разделитель поля.
--help
Выводит подсказку об использовании и выходит с успешным кодом возврата.
--version
Выводит информацию о версии на стандартный вывод и завершается.
Перевод
Перевел с английского Виктор Вислобоков 2:5054/8.34@Fidonet.org
Ну, как? Все понятно? Особенно что такое список-байтов, список-символов и список-полей (и главное - что это за поля такие)?
Теперь посмотрим английский ман. Напрасные старания, все те же загадочные поля. Я знаю только одни поля в текстовом файле - те, которые по краям страницы, но здесь речь явно не о них. Правда слово "fields" не столь однозначно, оно может обозначать области, регионы и прочее, но хотелось бы знать, что автор мана имел в виду применительно к файлу!? Не стану вас мучить и приводить английский ман, перевод очень точный. Поищем в Интернете.., есть ман от OpenBSD, тот поподробнее и - о, счастье! - два примера, от которых уже можно танцевать.
Результатам этих танцев, продолжавшихся целый рабочий день, и посвящена эта статья.
Команда cut
Командаcut
позволяет выбрать из каждой строки файла нужную часть (по единому правилу для всех строк) и показать выборку на экране дисплея.
Команда имеет три основные опции:
- -b - когда объектом выбора являются байты;
- -с - когда объектом выбора являются символы;
- -f - когда объектом выбора являются элементы форматирования текста (колонки, столбцы и прочее).
Внимание: Опции -c, -b, и -f могут употребляться только поодиночке.
Начнем с наиболее очевидного - символов (опция -с)
Опция -с
Например, возьмем файл/etc/shells
, в целом виде он выглядит так:
/bin/bash /bin/tcsh /bin/csh /bin/ash /bin/ksh /bin/zsh
Теперь применим команду:
$ cut -c 1,5 /etc/shells // // // // // //
В данном примере опция -c означает, что объектом выбора будут символы, цифры 1 и 5 означают, что мы выбираем первый и пятый символы строки (счет идет с 1), а все остальное содержимое файла игнорируется.
Можно выбирать символы не по порядковым номерам, а диапазонами:
$ cut -c 1-5 /etc/shells /bin/ /bin/ /bin/ /bin/ /bin/ /bin/
В этом случае мы выбрали символы в диапазоне с 1 по 5 (включительно).
Можно указать несколько диапазонов через запятую:
~$ cut -c 1-5,8-9 /etc/shells /bin/sh /bin/sh /bin/h /bin/h /bin/h /bin/h
Первые три примера имеют чисто демонстрационный характер и не имеют практического смысла. Следующий пример может претендовать на некий смысл:
$ cut -c 6- /etc/shells bash tcsh csh ash ksh zsh
Тут мы получили список доступных в системе шеллов. Для этого мы не стали указывать правую границу диапазона, что заставляет команду выдавать все содержимое строк от указанного символа до конца строки. Можно оставить прочерк с левой стороны, тогда выборка пойдет от начала строки до указанного символа.
Надеюсь, что с опцией -c ясность полная, можно переходить к следующей.
Опция -b
Весьма похожа на предыдущую опцию, как по способу задания выборки байт, так и по результатам, ведь в большинстве случаев один байт определяет один символ.
$ cut -b 1-6 /etc/shells /bin/b /bin/t /bin/c /bin/a /bin/k /bin/z
Мы выбрали первые 6 байт из каждой строки файла /etc/shells.
Точно так же как и с опцией -с, можно использовать способы выборки n,m; -n; и n-. Остается лишь добавить, что символы табуляции и backspace (возврат назад на один символ с удалением его) трактуются как любой другой символ - они и занимают один байт. (Не поручусь за национальные кодировки).
Опция -f
Объектом выбора данной опции являются те самые загадочные "поля", о которых я говорил в предисловии. Оказалось все просто. Выбираем мы колонки текста, или столбцы, или что еще там, разделенные знаком табуляции. Так как я таких файлов никогда не встречал, то пришлось создать специально для опытов. Вот содержимое файла tab.txt:
qwer tyui op[] asdf ghjk llll zxcv bnm, ....
А вот команда:
$ cut -f 1,2 tab.txt qwer tyui asdf ghjk zxcv bnm,
Все как ожидалось, выбраны две первые колонки. Еще пример:
$ cut -f 2- tab.txt tyui op[] ghjk llll bnm, ....
В общем понятно, схема та же, только с колонками. Вопрос в другом - где взять такие файлы с колонками, разделенными знаком табуляции, чтобы их обрабатывать?
К счастью, есть опция -d, предназначенная для работы в паре с опцией -f и понимающая другие разделители текста, кроме знаков табуляции. В директории /etc полно файлов, содержащих столбцы данных, разделенных всякими разделителями; беда только, что они довольно длинные для примеров. Я возьму первые десять строчек из файла /etc/group и создам файл group10.txt.
$ cut -f 1- -d : group10.txt root::0:root bin::1:root,bin,daemon daemon::2:root,bin,daemon sys::3:root,bin,adm adm::4:root,adm,daemon tty::5: disk:!:6:root,adm,haldaemon,ya,alex lp::7:lp,ya,alex mem::8: kmem::9:
В этом примере, опция -f приказывает отбирать все столбцы, с первого до последнего, а опция -d указывает на символ, являющийся разделителем -d : разделителем служит двоеточие. Выше на экране файл group10.txt полностью.
$ cut -f 1,3 -d : group10.txt root:0 bin:1 daemon:2 sys:3 adm:4 tty:5 disk:6 lp:7 mem:8 kmem:9
А сейчас мы отобрали первый и третий столбцы, то есть узнали идентификационный номер каждой группы. В остальном все те же правила выбора объекта, что и для прочих опций. Символы, разделяющие столбцы, разумеется, могут быть иными, нежели двоеточие. Их нужно задавать при помощи опции -d <символ>. Есть и более наглядный способ употребления опции -d. Вместо только что описанной конструкции (-d <символ>) пишем --delim=<символ>, это кажется более надежным, чем при помощи пробела.
Небольшая хитрость. Во многих файлах символом разделения служит пробел, или несколько пробелов подряд (например файл /etc/fstab). Чтобы указать разделитель для таких файлов, нужно заключить пробел в кавычки (одинарные или двойные); только тогда програма поймет, что разделителем служит пробел:
$ cut -f 1-21 -d " " /etc/fstab /dev/hda7 swap /dev/hdb5 swap /dev/hdb1 / devpts /dev/pts devpts proc /proc usbfs /proc/bus/usb /dev/hda1 /mnt/win_c /dev/hda5 /mnt/win_d /dev/fd0 /mnt/floppy
Как указать разделителем несколько пробелов, осталось неизвестным.
Опция -s
Опция -s употребляется с опцией -f и приказывает не выводить на экран строки, не содержащие символов-разделителей. Ясно даже мне.
Опция -n
Опция -n употребляется вместе с опцией -b (когда объектом выборки являются байты). Эта опция пишется первой и запрещает команде разбивать многобайтные символы. Другими словами, если символ записывается более чем одним байтом, и мы, указывая выборку, случайно попадем на такой многобайтный символ, то в выводе программы появятся вопросительные знаки, либо квадратики, свидетельствующие о том, что программа не до конца считала этот символ и не знает как его интерпретировать. Например:
$ cut -b 1-5 rus.txt йц? фы? яч?
(Символы кириллицы в кодировке UTF-8 состоят из 2 байтов). Стоит добавить опцию -n, как команда перестанет пытаться читать часть многобайтного символа:
$ cut -n -b 1-5 rus.txt йц фы яч
Опция --complement
Встречается в версиях команды cut от GNU Coreutils. Но редко встречается в манах. Опция употребляется совместно с опциями -b, -c и -f. Эта опция дополнит выборку всеми остальными объектами выбора. Другими словами, те объекты, которые вы укажете, не появятся в выводе команды, зато все остальные - появятся. Например:
$ cut -f 1 --complement tab.txt tyui op[] ghjk llll bnm, ....
Указанный первый столбец не появился, зато остальные два оказались в выводе команды. Опция очень удобна, когда у вас множество столбцов или колонок текста, а вам нужно распечатать их все, за исключением одной-двух-трех.
Опции --help и --version общеизвестны, и задерживаться на них я не буду.
Команда cut и символы кириллицы
Некоторые новейшие версии программы cut, в некоторых дистрибутивах, неплохо справляются с кириллическими символами. Другие версии, в других дистрибутивах не справляются вовсе. Я было попытался дать несколько примеров с кириллицей, но результаты на разных машинах, на разных дистрибутивах, и с разными версиями команды могли только сбить читателя с толку, не внеся никакой ясности. Поэтому общие рекомендации: не бойтесь пробовать работать с родным языком, если не получается, обновите версию программы, не выходит - попробуйте дистрибутив с другой кодировкой по умолчанию.Несколько слов о версиях
В Линукс дистрибутивах в основном встречается команда cut от GNU Coreutils. Программа разрабатывается и новые версии появляются регулярно. Советую иметь новейшую стабильную версию. Мне попадались версии не первой свежести, которые откровенно "глючили" и не различали, скажем, опций -b и -c (cut (GNU coreutils) 5.97), а я-то думал, что так и надо. Поэтому при первом подозрении попробуйте другой дистрибутив (или LiveCD).Резюме программы cut
Программа применима и эффективно работает с регулярными файлами, те есть с файлами, где из строчки в строчку повторяется некая структура информации (всякого рода списки, перечни, распечатки и прочее). Трудно представить себе, как ее можно использовать с обычным текстом, не разбитым на строки. Наличие трех подходов (байты, символы и столбцы) к определению выборки позволяют добиться успеха почти в любом случае, не одним способом, так другим. Особенно полезной может быть команда в качестве фильтра в составе программных каналов (pipes).Благодарности
Автор благодарит В.Костромина за ненавязчивую, но мудрую помощь.Большое спасибо всем авторам манов, за то, что не оставили без работы.
Автор будет благодарен всем дополнениям, поправкам и мнениям по данной статье и по проекту HuMan.