Наши партнеры

UnixForum






Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Работа в консоли Linux

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.



Средняя оценка 3 при 2 голосовавших