Уж я и не знаю, зачем вы это всё читаете, зато прекрасно знаю, для кого это написано: для тех, кому понадобилось научится применять одну из многих UNIX-Way утилит - GNUsed.
Вообще говоря, sed появилась более 30 лет назад, потому споры о том, что это чисто "линуксоидная" фишка, бессмысленны: существуют версии sed для MS-DOS, Windows, MacOS, да и наверное для всех систем где понятие текст имеет хоть какой-то смысл.
Что такое sed? Это (как вам уже наверняка известно) потоковый текстовый редактор. Текст поступает на обработку не в виде файла как обычно, а в виде потока. По этой причине, sed даже более универсальна, чем все остальные редакторы. Утилита sed может работать без участия оператора, без возможности вывода текста, на системах где вывод файлов вообще не возможен, и даже там, где не существует самих файлов! Достаточно всего-лишь потоков, а уж они есть практически везде.
Программы должны уметь обмениваться информацией. Это аксиома. Если программы этого не умеют, это не программы, а набор разбухших монстров, которые еле ворочаются на самых современных компьютерах. Примеры всем известны. Проблема только в том, что для обмена нужно выработать правила взаимодействия, в основном, в каком виде обмениваться? Много лет назад, ещё во времена UNIX, было решено обмениваться исключительно текстовой информацией, и появилось соглашение, что считать текстом, а что - нет. Конечно, многие программы используют какие-то особые, специальные форматы, однако, обмениваться ими в общем случае невозможно (если конечно нет подходящего конвертера спец-формат<->текст). Соглашения следующие:
Особый случай - это "чистый текст(plain-text)", алфавит в нём состоит из байтов 32...127, 10, и 9.
Если пользователь, а тем более программист не согласен с этими соглашениями, то у него возникают проблемы.
Примеров - масса: я сам, помнится, расстраивался, что у меня "не работает" планировщик - я дописал к его таблице свою строчку, однако планировщик меня тупо игнорировал. Всё просто, не было никакой строчки, была фигня непонятная! Я нарушил пункт 2 - не добавил в конец строки '\n'. Хотя это скорее беда моего редактора, просил-ведь: "сохрани как текст", а он...
Особо отмечу проблемы с текстами в UTF-8. В них символы могут быть в несколько байтов, но это ещё не самое страшное (нас это обычно не сильно волнует, это проблема разработчиков sed, мы можем заметить разве-что сильное уменьшение быстродействия). Самое противное - в "тексте" могут появляться несимволы, что приводит к совершенно неожиданным результатам.
Первую свою программу я написал лет 20 назад. Однако историю я знаю ещё глубже - дело в том, что в то время (впрочем как и сейчас) новейший супер-компьютер мне никто не дал, пришлось мучиться на довольно старой технике. Именно по этому я и знаю, какими были тогда текстовые редакторы.
Основная (для меня) прелесть Linux заключается в том, что мы можем всё сразу попробовать. Достаточно открыть второе окно (вторую консоль для некромантов), и там набирать команды. ИМХО, если у вас хорошо развита моторная память, вам лучше команды именно набирать, тем-же, у кого более развита зрительная - можно копировать мышкой (кстати, я именно так и делаю).
Раз уж зашла речь о программах, давайте напишем программу на C.
Пример 1.1. Программа test.c.
#include <stdio.h> /* comment */ int main() { printf("тестовый файл\n"); return 0; }
Что делает эта программа не столь важно (если вам интересно - то всё что она сделает будучи скомпилированной - выведет на экран фразу "тестовый файл" и завершит работу), нам интересна эта программа всего-лишь как образец текста. Попробуем отредактировать эту программу так, как это делал я более 20 лет назад:
$ed test.c 90
программа ed написала 90 и что-то ждёт. Ну 90 - это размер файла для редактирования, а ждёт наш редактор команды... Первое что хочется сделать - просмотреть файл. Для этого существует команда p, которая выведет нужные нам строки. Какие именно? Это нужно указать явно, по умолчанию будет выведена только последняя строка, записав 1,$p мы выведем все строки нашего файла. Тут 1,$ означает диапазон строк, от первой строки, и до последней (последняя строка обозначается $
). Это выражение называется адресным, либо просто - адресом, так-как оно определяет, к каким именно строкам будет применена данная команда.
Теперь отредактируем наш файл, к примеру заменим "return 0;", на "return 77;". Как всегда, для этого существует множество путей, наверное самый простой, это заново набрать всю строчку. Команда замены строчек у нас есть, называется она c; однако, нужно ещё и указать, к чему-же её применить (к какой именно строке). Проще всего указать номер этой строки, но его тоже надо узнать (хотя можно и посчитать, но это не наш метод), наберём 1,$n:
1 #include <stdio.h> 2 3 /* comment */ 4 5 int main() 6 { 7 printf("тестовый файл\n"); 8 return 0; 9 } 10
Эта команда сработала так-же как p, только перед каждой строкой вывелся её номер, и теперь ясно, что нам нужно изменить восьмую строчку. Для этого наберём 8c, и теперь наберём строчку по новой, нажмём ENTER и CTRL+C. Просмотрев файл, мы убедимся, что замена выполнена.
Согласитесь, неудобно. Однако, в те далёкие семидесятые годы прошлого века ничего другого придумать было нельзя, текст на экране терминала безвозвратно уползал вверх, и мы видели только последние 24 строки (в 25й вводилась команда). Навигация по тексту как в современных редакторах была невозможна, потому пришлось придумать другие методы. Впрочем тут и придумывать ничего не надо: просто нужно заменить в строке 8 число 0 на число 77. Для этого (кто-бы мог подумать) имеется команда замены. Я долго не понимал, почему эта команда называется s, а не более логично, например replace. Точно это мне неизвестно до сих пор, но думается, что главное в этой команде вовсе не замена, а поиск (search), нам сначала надо найти число 0, и уж затем, если найдём конечно, его заменить. Записывается это просто: 8s/0/77/, т.е. "в восьмой строке нужно заменить 0 на 77".
Но на практике и это неудобно - проще было-бы не нам смотреть номер строки с "return", а заставить это сделать компьютер. И конечно это ещё тогда было реализовано: в качестве адреса можно задать не только номер, но и саму строку, или даже часть строки, наберём к примеру /ret/n:
8 return 0;
Как видите, ed самостоятельно находит строку с /ret/
, и выполняет для неё заданную команду.
/begin/,/end/
, для всех строк начиная со строки со словом "begin", и кончая строкой со словом "end", либо к примеру /start/,$
, что значит: от строки со словом "start" и до конца текста. Например (для нашей программы):
/{/,/}/p{ printf("тестовый файл\n"); return 77; }Если диапазон(ы) не найден(ы), то ed среагирует вопросиком, как на неправильную команду (забегая вперёд, скажу что sed действует по другому).
Редактор ed конечно не самая удобная штука, но на оборудовании 70х ничего лучше придумать было нельзя. К счастью, прогресс не стоит на месте, и с развитием железа развивались и программы для него, в частности текстовые редакторы. Все вы прекрасно знаете, во что превратились сегодня текстовые редакторы - достаточно сказать, что даже самые опытные пользователи попросту не знают 80% возможностей своего любимого редактора! Однако, была и другая ветка развития текстовых редакторов: во многих случаях нет нужды каждый раз писать новые файлы с нуля, часто нужно просто исправлять какой-либо файл по известному алгоритму, это действие конечно можно произвести обычным редактором, но на самом деле, присутствие юзера тут не только не необходимо, но даже вредно! Юзерам свойственно постоянно ошибаться, всё путать да и вообще - юзер, ленивое и капризное существо: если ему было сказано: "сотри в файле %WINDOWS%\sysok.ini все слова hide", а юзер стёр не все, не hide, да и вообще не то(хорошо, если слова в файлах стирал, а не сами файлы), то этот самый юзер будет обвинять меня, вас, глючный компьютер, кривую программу, карму, да что угодно, но только не свою криворукость...
Имеется ещё 1000 и 7 разных применений, где участие юзера нужно если не исключить, то хотя-бы сильно ограничить: например огромный класс задач про безопасность, ну сколько раз можно повторять: "Читай логи!!!", дык пробовал, "ниасилил - многабукв". Правильно, что-бы юзер увидел опасность необходимо отфильтровать весь "мусор", компьютеру всё равно, он железный: было 10482 атаки на закрытую уязвимость, и одна успешная на открытую - в логе будет 10483 строки (в лучшем случае), и даже если юзер - терпеливая и прилежная блондинка, то даже тогда, она скорее сломает PageDown (сотрёт колесо мыши), прежде чем найдёт нужную строчку.
Ну по поводу фильтров можно возразить: дескать в том-же ed можно набрать g/re/p, что приведёт к фильтрации только нужных строк. Та-же функциональность присутствует во всех остальных текстовых редакторах (включая notepad), мало того, для этого и редактор не нужен, можно прямо в консоли набрать grep (ну вы поняли, почему эта команда так названа). Всё это так, но для фильтрации этого зачастую мало, лично мне по любому не осилить ни 10483 не фильтрованные, ни 2174 фильтрованные строки: до того, как я научился использовать sed, мне приходилось составлять зубодробительные конвейеры, а потом всё равно юзать less|PageDown|search, в разных комбинациях. Это не очень сложно, но отнимает массу времени.
В фильтрации, да и не только в ней, часто нужно реализовать очень простой алгоритм, который почему-то не реализован в различных имеющихся утилитах. Писать для этого программу на C лениво да и не быстро. Для таких случаев придуманы скриптовые языки программирования(ЯП), например bash, perl, awk, php, и многие другие. Все они имеют два недостатка:
#!/bin/bash echo $VARIABLEАга. На 10000 строк! Это-ж каждый раз надо прочитать из файла слово "echo", разобраться что оно значит, а потом найти нужную $VARIABLE... Такой скрипт будет выполнятся в сотни раз дольше чем сам вывод!
Таким образом, нам необходим особый ЯП, который лишён этих недостатков. Таким языком как раз и является sed.
Примитивные задачи.
С такими задачами справятся доступные утилиты, если нам нужно просто скопировать информацию, или скопировать несколько файлов в один, нам нужна cat, для резки файлов подойдёт split и cut, для поиска подстрок сгодится grep, и так далее.
Задачи, для которых не хватает инструментов из п1
А вот тут-то и пригодится sed.
Ещё более сложные задачи.
Если мощности sed не хватает, придётся писать собственный анализатор текста. При этом не стоит забывать про sed - можно сэкономить огромное количество времени (как своего, так и процессорного), если прогнать входные и/или выходные данные через sed-фильтр(ы).
Недоступные для решения на компьютере задачи.
Да, есть и такие... Что-ж, вот тут-то и пригодятся обычные редакторы, например этот текст я набирал в kate. Однако, многие части у меня уже были готовые, потому я их прямо суда вставил, прогнав через sed конечно.
Вы можете обсудить этот документ на форуме. Текст предоставляется по лицензии GNU Free Documentation License (Перевод лицензии GFDL).
Вы можете пожертвовать небольшую сумму яндекс-денег на счёт 41001666004238 для оплаты хостинга, интернета, и прочего. Это конечно добровольно, однако это намного улучшит данный документ (у меня будет больше времени для его улучшения). На самом деле, проект часто находится на грани закрытия, ибо никаких денег никогда не приносил, и приносить не будет. Вы можете мне помочь. Спасибо.