Как начать работу с потоковым редактором sed?

Урок русского языка в Грузинской школе.
Училка:
— Дэти! Это нэвозможна панат лагически.
Паэтому просто запоминаэм.
Слово «от вас» пишется раздэльно,
а слово «к вас» — слитно.

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

Вообще, потоковый редактор (не только sed) предназначен для автоматической обработки текстовых файлов. Хорошо, но что значит «обработка»? Давайте прикинем — какие вообще могут быть обработки текста?

Ну, первое, что приходит на ум — это замена слов. Это раз.

Далее. Поскольку редактор sed обрабатывает текст порциями, а порцией считается одна строка (которая заканчивается символом «новая строка»), то — редактор должен уметь заменять целые строки. Это два.

Хорошо. А еще что-нибудь можно нагрузить на потоковую обработку текста?

Ну, наверно, сюда можно было бы отнести также удаление строк и вставку новых строк. Это три и четыре.

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

Таким образом, мы можем начать изучение редактора sed не с ознакомления и заучивания его ключей и параметров, а несколько необычным методом. Давайте представим, что мы сами сейчас изобретаем (создаем) потоковый редактор с нуля.

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

— замена указанного слова (s, от «substitude» —  подстановка):
— удаление строки (d, от «delete» — удалить), на которую укажем;
— вставка строки до (i, от «insert» — вставить) и добавление строки после (a, от «append» — добавить) указанной;
— заменить указанную строку (c, от «change» — замена);

Это основные команды. На самом деле sed может выполнять больше команд, но нам сейчас важно начать работать с ним, а не иметь исчерпывающие мертвые знания.

Таким образом, на данный момент мы уже примерно знаем чего можно, а чего нельзя требовать от sed.

Теперь давайте попрактикуемся.

Подстановка

Давайте в качестве подопытного текста возьмём сказку про Колобка и заменим слово «Колобок» на слово «Кирпич». Для этого выполним следующую команду:

$ sed s/Колобок/Кирпич/g fairytale.txt > new-fairytale.txt

Итак, что мы тут имеем. (Пристегните ремни, ибо логика команд редактора sed — это что-то! Но к счастью, этого сумасшествия не так много. Терпите!)

Мы видим, команду s (substitude, замена), далее следует символ ‘/’. Это символ-разграничитель полей. Первое поле — слово «Колобок» — это то, что мы ищем в тексте. Следующее поле — слово «Кирпич» — это то, чем мы будем заменять слово из первого поля.

После этих полей следует символ g. Это — флаг «global», который сообщает редактору, что следует производить замены всех слов «Колобок», которые присутствуют в строке, на слово «Кирпич». Если этот флаг не указывать, то sed произведет замену первого встретившегося слова «Колобок» и перейдет к следующей строке, и если в этой строке присутствуют еще слова «Колобок», то они останутся нетронутыми. Но это не наш вариант. Нам интереснее заменить все слова, поэтому указываем флаг.

Если вместо флага g написать цифру, то sed будет искать в строке слово из перового поля, подсчитывать их не изменяя — но произведет замену лишь только того слова, порядковый номер которого соответствует цифре.

Например, у нас в строке 15 раз встречается слово «Колобок.» И если мы вместо флага g укажем цифру 8, то только восьмое по счету слово «Колобок» будет заменено на слово «Кирпич». Остальные слова останутся нетронутыми.

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

Мы видим, что далее в командной строке идет имя файла — fairytale.txt. Это ни что иное как имя исходного файла, над которым мы производим манипуляции.

По умолчанию sed направляет результат своих преобразований в стандартный выход (то есть в консоль). При необходимости мы можем перехватить вывод и направить его в файл, что мы и сделали с помощью конструкции «> new-fairytale.txt«.

Вообще надо отметить, что многие утилиты в Линуксе не изменяют исходных файлов, а результат выводят на консоль. Такой подход гарантирует безопасность операций — если внезапно что-то пойдет не так, то вы ничего не сломаете. Пользуйтесь этой особенностью!

Удаление строки

Потоковый редактор sed позволяет удалять не только одну строку (это банально!),  а целый диапазон строк.

Так, например, команда

$ sed '15d' fairytale.txt

удалит пятнадцатую строку. Полученный текст (без 15-ой) строки будет выведен на терминал. Можете проверить. Как я уже обращал ваше внимание выше — sed не изменяет исходный текст. Не поленитесь, потренируйтесь! И опять же, при необходимости полученный результат можно сохранить в файле.

Следующая команда

$ sed '20,40d' fairytale.txt

удалит сразу 21 строку — с 20-ой по 40-ю включительно.

Можно удалить все строки — начиная с указанно и до конца файла. Для этого вместо второй цифры в команде нужно поставить знак доллара:

$ sed '20,$d' fairytale.txt

Вставка и добавление строки

Команды Вставка и Добавление строк очень похожи друг на друга — и та, и другая добавляют строку в текст. Разница состоит в том, что «Вставка» вставляет строку перед указанной строкой, а «Добавление» — добавляет после указанной строки. Осталось понять, что такое указанная строка и как ее указать.

Да очень просто! Например, эта команда вставляет строку «А ну-ка, тетя, подвинься!» перед третьей строкой текста:

$ sed '3i\А ну-ка, тетя, подвинься!' fairytale.txt

Грубо говоря, был текст такой:

Шаланды полные кефали
В Одессу Костя приводил,
И все бендюжники вставали,
Когда в пивную он входил.

А стал такой:

Шаланды полные кефали
В Одессу Костя приводил,
А ну-ка, тетя, подвинься!
И все бендюжники вставали,
Когда в пивную он входил.

А если вместо «вставки» выполнить «добавление»:

$ sed '3a\А ну-ка, тетя, подвинься!' fairytale.txt

, то получим

Шаланды полные кефали
В Одессу Костя приводил,
И все бендюжники вставали,
А ну-ка, тетя, подвинься!
Когда в пивную он входил.

Замена строки

Тут тоже все просто. Вместо указанной строки нам нужно влепить другую. Например, команда

$ sed '3c\Дирекция охрану вызывала,' fairytale.txt

Выдаст на консоль следующий «выхлоп»:

Шаланды полные кефали
В Одессу Костя приводил,
Дирекция охрану вызывала,
Когда в пивную он входил.

И, пожалуй, на этом изучение sed мы закончим.

Случай из жизни.

Пару лет назад, я работал в одной компании. Я снимал показания приборов и записывал их в файл. Ну, понятно, что не сам я это делал, а Линукс впахивал. Но прогу для приема данных с USB-порта и записи их в файл писал я, поэтому все претензии по формату записей ко мне.

Запись производилась в текстовый файл. Каждая запись состояла из нескольких колонок чисел с плавающей точкой. Колонки отделялись друг от друга символом «запятая».

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

Однако, возникла неразрешимая проблема — коллега знал только Шиндовс. Более-менее ориентировался в Икселе и в принципе мог бы в нем построить графики. Но Иксель напрочь отказался засасывать файл, в котором плавающая точка была точкой, а не запятой. Это какой-то нонсенс! Вся проблема-то, с точки зрения Джедая, состояла в том чтобы запятую (разграничитель полей) заменить на символ точка-с-запятой, а плавающую точку — на запятую.

Что делает в таких случаях Виндузятник?

Поскольку файл — это плоский (без оформительских элементов) текст, то коллега запускает Notepad и пытается загрузить в него миллион строк. Блокнот несколько раз разрывает на куски вместе с операционной системой… Ну, блокнот в принципе не обрабатывает файлы объемом более 64 килобайт.

Проблем нет! Комп у коллеги — навороченный, ВОСЕМЬ!!! горшков по 3.5 ГГц каждый, памяти не то 4, не то 8 Гигов. Короче, дури хватает! С такой мощью не победить проблему — ну, для этого нужно обладать особым талантом!

Коллега выкидывает нахрен пистолет «Notepad» и достает базуку «Word». Вы вникаете в ситуацию? Вы чувствуете типовой подход к решению проблем у виндузятников?

Базука с успехом засосала весь текст. Ура! Мы почти победили. Ща мы заменим символы и скормим полученный файл Икселю!

После дву-трех часов работы, у меня образовалась пауза, и я поинтересовался у коллеги, как идут дела. Он ответил что-то типа:

— Да, нормально. Щас заменю запятые и …

Ага. «Шас» — это время оказалось не менее 6 часов.

Пришлось выполнять всю работу самому. Замена «запятых» на «точку-с-запятой» — полсекунды, еще полсекунды на замену «точки» на «запятую». Файл готов. Вручаю ему файл в новой редакции и говорю, чтобы он не вырубал свой мега-комп, просто очень хочется знать — за какое время Винда справится с задачей.

Винда не справилась. Как я уже говорил, прошло шесть часов, а результата не было. Мы решили скотину более не мучить, а пойти домой, ибо рабочий день уже кончился, а базука так и не смогла поменять хотя бы запятые.

Графики я построил сам. Загрузил gnuplot и «нарисовал», что требовалось. Да, забыл упомянуть, что моя тачка — это древний Селерон-2.4 ГГц с 512 МБ оперативы.

Реклама

2 responses to “Как начать работу с потоковым редактором sed?

  1. Коллега, спасибо огромное за текст! Нашел его через гугль, когда столкнулся с такой же проблемой как и у тебя в «случае из жизни», только у меня файл был из 100 000 строк.

    Не удержался и перепостил у себя. У нас город далекий, с инетом туго, поэтому копипащу частенько для себя, и местных коллег. Ссылку на оринигал сделал.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s