|
|||||||
Поставь все на конвейер
Время создания: 25.11.2009 21:54
Автор: Журнал "Хакер", номер 73, j1m@list.ru
Текстовые метки: linux, bash, awk, sed, tr, конвейер, поток, строка, обработка
Раздел: Компьютер - Linux - Bash - Команды и скрипты
Запись: xintrea/mytetra_syncro/master/base/0000001317/text.html на raw.github.com
|
|||||||
|
|||||||
Анализ и преобразование текстовых потоков *nix славится своими программами-фильтрами. Множество маленьких программок, каждая из которых выполняет только одну определенную функцию, наполняют каталоги /bin и /usr/bin. С помощью таких фильтров, как cut, grep, sed, можно привести к нужному виду практически любой поток текстовой информации. Появившись около тридцати лет назад, они и по сей день активно применяются, что доказывает эффективность конвейерной обработки информации. Маленькие помощники Две наиболее часто выполняемые над текстом операции - сортировка и поиск. Начнем с сортировки, а поиск рассмотрим позже. Для сортировки строк применяется команда sort (кто бы мог подумать :), которая читает входной поток и пишет отсортированные строки в выходной поток. У программы есть несколько интересных флагов: -f - игнорировать регистр букв, -d - сортировать только по буквам и цифрам, -n - сортировать по цифрам, -r - обратная сортировка. Команде можно указать, по какому полю выполнять сортировку. Поля - это последовательности символов, разделенные пробелом или табуляцией. Для этого достаточно указать флаг +номер_поля. Так, можно отсортировать список файлов по размеру: $ ls -l | sort +5 -n Для разбиения строк удобно использовать cut. С помощью этой программы можно вырезать из строк отдельные части, которые и будут выведены на экран. Приведем пример: $ echo UNIXLinuxBSD | cut -c 5-10 На экран будет выведено «Linux». Как это работает? С помощью флага -c мы задали диапазон позиций символов, которые хотим увидеть. Слово «Linux» как раз и занимает позиции с пятой по десятую в строке «UNIXLinuxBSD». Одним из основных достоинств cut является способность работать с полями. Для этого предусмотрено два флага: -d разделитель_полей и -f список_полей. С помощью первого можно указать символ, который будет использоваться в качестве разделителя полей (по умолчанию знак табуляции), а с помощью второго - список выводимых полей. Пример: $ date Сбт Ноя 13 17:57:08 GMT+6 2004 $ date | cut -d " " -f 4 17:57:08 Здесь мы указали в качестве разделителя полей знак пробела и вывели на STDOUT четвертое поле. Довольно интересной и полезной программой является tr(1). Она заменяет символы, указанные в первом аргументе, на соответствующие символы во втором аргументе. Так, команда $ cat file | tr a e заменит все буквы «a» на «e». Можно использовать диапазоны: $ cat file | tr 'a-z' 'A-Z' и заменить все строчные буквы прописными - это, кстати, наиболее частое применение этой команды. Указав флаг -d, можно удалять символы из текста. Часто бывает необходимо просто подсчитать количество строк или слов в тексте. Это легко проделать при помощи простенькой программки wc(1). По дефолту она печатает количество строк, слов и символов во входном потоке. С помощью флагов можно указать, что именно необходимо вывести на экран: -c - символы, -l - строки или -w - слова. Отдельно стоит упомянуть о двух программах: head(1) и tail(1). Первая используется для просмотра первых десяти строк файла, а вторая - последних десяти. Программы очень похожи и управляются идентичными флагами. Так, с помощью флага -n можно изменить количество печатаемых строк, а флаг -c позволяет измерять порцию выводимых данных не в строках, а в байтах. Помимо этих ключей, tail принимает очень полезный (и полюбившийся админам) флаг -f. После запуска с этим флагом программа не закончит свою работу, а продолжит выводить данные по мере их поступления. Для слежения за логами лучшего решения не найти. Найдется все! Назначение утилиты grep(1) - поиск в текстовых файлах. Он выдает все строки, содержащие образец поиска. Например команда $ ls | grep .txt покажет имена файлов с расширением .txt. В качестве образца поиска можно использовать регулярное выражение. Некоторые полезные флаги: -E - использовать расширенные регулярные выражения (egrep является синонимом grep –E), -i - игнорировать регистр букв, -v - выводить строки, не соответствующие образцу, -n - выводить номера строк, -f - читать образец поиска из файла, --color - подсвечивать совпадения. Долой интерактивность! Ты видел редактор без интерфейса и вообще без интерактивного общения с пользователем? Нет? Ты многое потерял, тебе просто необходимо познакомиться с sed(1). Потоковый редактор sed предназначен для редактирования текста на лету. Он читает входной поток, выполняет необходимые преобразования в соответствии с указанными командами и записывает результат в выходной поток. Sed управляется командами, многим из которых может предшествовать адрес (номер строки или регулярное выражение, заключенное в «/») или диапазон адресов (два номера строки, разделенные запятой), последняя строка адресуется с помощью символа «$». Любая команда может быть задана без указания адреса, в этом случае она будет применена ко всем строкам. Чтобы не запутаться, команды, принимающие адреса, я буду предварять знаком «[x]», а команды, принимающие адреса или диапазоны адресов, знаком «[x,x]». Так что же можно сделать с помощью sed? 1. Его удобно использовать для замены слов в тексте с помощью команды [x,x] s/регулярное_выражение/замена/флаги. Например команда $ cat file.txt | sed 's/UNIX/Linux/g' > file2.txt заменит все слова UNIX на Linux и запишет результат в file2.txt. Флаг g нужен, если слово UNIX встречается несколько раз в одной строке. 2. Добавлять произвольную строку в поток командой [x]a\. Команда $ cat file.txt | sed '10a\Здесь был я.' вставит строку «Здесь был я.» после десятой строки. 3. Заменять произвольные строки командой [x]i\, которая работает подобно команде [x]a\. 4. Удалять строки командой [x,x]d: $ cat file.txt | sed '10,$d' $ cat file.txt | sed '/Windows/d' Первая команда удалит строки с десятой до последней, а вторая - все строки, содержащие слово «Windows». 5. Добавлять содержимое другого файла в поток командой [x]r файл. 6. Использовать вместо tr. Для этого есть команда [x]y/источник/цель/ (эквивалент: tr источник цель). 7. Использовать вместо head: $ cat file.txt | sed 10q Команда [x]q приводит к немедленному завершению работы sed. Поэтому в приведенном примере напечатается только десять первых строк, а на десятой строке произойдет выход из редактора. 8. Использовать вместо grep: $ cat file.txt | sed -n '/образец/p' По дефолту sed печатает все строки из входного потока в выходной, такое поведение можно изменить, используя флаг -n. Теперь печать строк можно задать только командой [x,x]p. В приведенном выше примере будут выведены только строки, совпадающие с образцом, что эквивалентно команде $ cat file.txt | grep образец 9. Применять приемы программирования. Можно написать небольшой сценарий для sed и сохранить его в файле. Внутри командного файла можно указывать метки и перемещаться между ними. К сожалению, эта тема выходит за рамки данной статьи. Sed может делать с текстом очень многое, для дальнейшего изучения советую почитать info-страницу. Найти и обработать Вот и добрались наши руки до одного из самых мощных и сложных инструментов, предназначенных для редактирования текста - awk. Это язык поиска и обработки шаблонов, по синтаксису он подобен языку C. В нем присутствует даже всеми любимая функция printf. Awk позиционировался авторами как более мощная замена sed, поэтому программы awk похожи на сценарии sed. Программа состоит из пар шаблон-действие, имеющих вид шаблон { действие } где шаблон может быть: отношением (<, > , ==, != и т.д.); регулярным выражением, заключенным в «/»; сопоставлением шаблону (~, !~); комбинацией всего перечисленного. Действие - это оператор или блок операторов, разделенных «;». Каждая входная строка сравнивается с шаблоном из каждой пары шаблон-действие. В каждой паре либо шаблон, либо действие может отсутствовать. В случае если не указан шаблон, действие выполняется для каждой входной строки. Если не указано действие, оно назначается по умолчанию - печать строки. После запуска программы все входные строки разбиваются на поля. Поля помещаются в переменные: $1, $2, $3 и т.д. Вся строка адресуется переменной $0. Пример: $ date | awk '{ print $4 }' В этом примере шаблон опущен. С помощью оператора print распечатывается четвертое поле. Без указания аргументов print распечатает всю строку. По дефолту в качестве разделителя полей используется пробел. Указать другой разделитель можно, используя флаг -F. Еще пример: $ cat /etc/passwd | awk -F: '/boris/ { print $3, $6 }' Эта команда напечатает uid (третье поле) и домашний каталог (шестое поле) пользователя с ником boris. Помимо $1, $2, $N, в awk имеется еще несколько встроенных переменных, самые важные из которых:
Помимо встроенных переменных, присутствуют также встроенные шаблоны: BEGIN и END. Действие шаблона BEGIN выполняется до начала чтения входного потока, а действие шаблона END - после прочтения последней строки потока. Теперь посмотрим, что нам дает использование встроенных переменных и шаблонов, для этого возьмем команду $ cat /etc/passwd | awk 'BEGIN { FS=":" } /boris/ { print $3, $6 }' Этот пример аналогичен предыдущему. При введении новых переменных в awk-программу объявлять их не нужно, они будут создаваться при инициализации. Причем переменная сама примет необходимый тип в зависимости от операций, выполняемых над ней: $ awk 'BEGIN { a = 13 + 17; print a }' $ awk 'BEGIN { a = "UN" "IX"; print a }' По окончании выполнения первой команды на экран будет выведено число 30, а вторая команда выведет слово «UNIX». Конкатенация (слияние) строк выполняется операцией «пробел». Арифметические операции такие же, как в языке C. Массивы могут быть ассоциативными (как хэши в perl), то есть запись вида circle[color] = red; воспринимается интерпретатором нормально. В awk присутствуют все стандартные управляющие операторы, такие как ветвления и циклы. В большинстве своем они повторяют операторы языка C. Вот только не знаю, как часто тебе придется ими пользоваться. При работе с текстом они редко бывают нужны. Напоследок рассмотрим пример: $ cat file | awk ' length > 72 { printf("%s %d %s\n", "Строка", NR, "длинная."); long++; next; } { printf("%s %d %s\n", "Строка", NR, "короткая."); short++; } END { printf("%s %d\n", "Всего длинных строк:", long); printf("%s %d\n", "Всего коротких строк:", short); }' Это маленькая программа подсчитывает количество длинных и коротких строк в файле. Как ты уже, наверное, заметил, она состоит из трех блоков шаблон-действие. В первом блоке выясняется, длиннее ли строка 72-х символов (по умолчанию length вызывается с параметром $0). Если результат положительный, выводится сообщение и увеличивается счетчик (переменная long). Далее следует обратить внимание на оператор next, который принуждает интерпретатор перейти к обработке следующей строки. Таким образом, действие второго блока будет выполнено только в случае невыполнения действия первого блока. Последний блок END будет выполнен в самом конце и выведет общее количество коротких и длинных строк. Некоторые встроенные функции awk
Регулярные выражения стандарта POSIX Атомы (может быть любым неспециальным символом):
Классы (тоже являются атомами):
За атомами может следовать:
Атом, за которым следует один из этих символов, называется частью. Часть или несколько частей образуют ветвь. Полное регулярное выражение состоит из одной или более ветвей, разделенных символом «|», который выступает в качестве логического «или». Заключение Столь странное название язык awk получил в наследство от своих авторов. AWK - это первые буквы фамилий: Aho, Weinberger и Kernighan. Потоковый редактор sed был создан на базе редактора ed Л. Мак-Махоном. Скрипты sed и awk не обязательно вызывать с помощью ключа -f, можно прописать в начало скрипта строку «#!/bin/sed –f» или «#!/bin/awk –f», сделать файл исполняемым и запускать как обычный бинарник. |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|