Главная >> Команды >> Команда sed Linux

Команда sed Linux

Команда sed - это потоковый редактор текста, работающий по принципу замены. Его можно использовать для поиска, вставки, замены и удаления фрагментов в файле. С помощью этой утилиты вы можете редактировать файлы не открывая их. Будет намного быстрее если вы напишите что и на что надо заменить, чем вы будете открывать редактор vi, искать нужную строку и вручную всё заменять.

В этой статье мы рассмотрим основы использования команды sed linux, её синтаксис, а также синтаксис регулярных выражений, который используется непосредственно для поиска и замены в файлах.


Содержание статьи

Команда sed в Linux

Сначала рассмотрим синтаксис команды:

$ sed опции -e команды файл

А вот её основные опции:

  • -n, --quiet - не выводить содержимое буфера шаблона в конце каждой итерации;
  • -e - команды, которые надо выполнить для редактирования;
  • -f - прочитать команды редактирования из файла;
  • -i - сделать резервную копию файла перед редактированием;
  • -l - указать свою длину строки;
  • -r - включить поддержку расширенного синтаксиса регулярных выражений;
  • -s - если передано несколько файлов, рассматривать их как отдельные потоки, а не как один длинный.

Я понимаю, что сейчас всё очень сложно, но к концу статьи всё прояснится.

1. Как работает sed

Теперь нужно понять как работает команда sed. У утилиты есть два буфера, это активный буфер шаблона и дополнительный буфер. Оба изначально пусты. Программа выполняет заданные условия для каждой строки в переданном ей файле.

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

Когда всё команды будут выполнены и не указана опция -n, содержимое буфера шаблона выводится в стандартный поток вывода перед этим добавляется обратно символ перевода строки. если он был удален. Затем запускается новая итерация цикла для следующей строки.

Если не используются специальные команды, например, D, то после завершения одной итерации цикла содержимое буфера шаблона удаляется. Однако содержимое предыдущей строки хранится в дополнительном буфере и его можно использовать.

2. Адреса sed

Каждой команде можно передать адрес, который будет указывать на строки, для которых она будет выполнена:

  • номер - позволяет указать номер строки, в которой надо выполнять команду;
  • первая~шаг - команда будет выполняется для указанной в первой части строки, а затем для всех с указанным шагом;
  • $ - последняя строка в файле;
  • /регулярное_выражение/ - любая строка, которая подходит по регулярному выражению. Модификатор l указывает, что регулярное выражение должно быть не чувствительным к регистру;
  • номер, номер - начиная от строки из первой части и заканчивая строкой из второй части;
  • номер, /регулярное_выражение/ - начиная от строки из первой части и до строки, которая будет соответствовать регулярному выражению;
  • номер, +количество - начиная от номера строки указанного в первой части и еще плюс количество строк после него;
  • номер, ~число - начиная от строки номер и до строки номер которой будет кратный числу.

Если для команды не был задан адрес, то она будет выполнена для всех строк. Если передан один адрес, команда будет выполнена только для строки по этому адресу. Также можно передать диапазон адресов. Тогда адреса разделяются запятой и команда будет выполнена для всех адресов диапазона.

3. Синтаксис регулярных выражений

Вы можете использовать такие же регулярные выражения, как и для Bash и популярных языков программирования. Вот основные операторы, которые поддерживают регулярные выражения sed Linux:

  • * - любой символ, любое количество;
  • \+ - как звездочка, только один символ или больше;
  • \? - нет или один символ;
  • \{i\} - любой символ в количестве i;
  • \{i,j\} - любой символ в количестве от i до j;
  • \{i,\} - любой символ в количестве от i и больше.

4. Команды sed

Если вы хотите пользоваться sed, вам нужно знать команды редактирования. Рассмотрим самые часто применяемые из них:

  • # - комментарий, не выполняется;
  • q - завершает работу сценария;
  • d - удаляет буфер шаблона и запускает следующую итерацию цикла;
  • p - вывести содержимое буфера шаблона;
  • n - вывести содержимое буфера шаблона и прочитать в него следующую строку;
  • s/что_заменять/на_что_заменять/опции - замена символов, поддерживаются регулярные выражения;
  • y/символы/символы - позволяет заменить символы из первой части на соответствующие символы из второй части;
  • w - записать содержимое буфера шаблона в файл;
  • N - добавить перевод строки к буферу шаблона;
  • D - если буфер шаблона не содержит новую строку, удалить его содержимое и начать новую итерацию цикла, иначе удалить содержимое буфера до символа перевода строки и начать новую итерацию цикла с тем, что останется;
  • g - заменить содержимое буфера шаблона, содержимым дополнительного буфера;
  • G - добавить новую строку к содержимому буфера шаблона, затем добавить туда же содержимое дополнительного буфера.

Утилите можно передать несколько команд, для этого их надо разделить точкой с запятой или использовать две опции -e. Теперь вы знаете всё необходимое и можно переходить к примерам.

Примеры использования sed

Теперь рассмотрим примеры sed Linux, чтобы у вас сложилась целостная картина об этой утилите. Давайте сначала выведем из файла строки с пятой по десятую. Для этого воспользуемся командой -p. Мы используем опцию -n чтобы не выводить содержимое буфера шаблона на каждой итерации, а выводим только то, что нам надо. Если команда одна, то опцию -e можно опустить и писать без неё:

sed -n '5,10p' /etc/group

Или можно вывести весь файл, кроме строк с первой по двадцатую:

sed '1,20d' /etc/group

Здесь наоборот, опцию -n не указываем, чтобы выводилось всё, а с помощью команды d очищаем ненужное. Дальше рассмотрим замену в sed. Это самая частая функция, которая применяется вместе с этой утилитой. Заменим вхождения слова root на losst в том же файле и выведем всё в стандартный вывод:

sed 's/root/losst/g' /etc/group

Флаг g заменяет все вхождения, также можно использовать флаг i, чтобы сделать регулярное выражение sed не зависимым от регистра. Для команд можно задавать адреса. Например, давайте выполним замену 0 на 1000, но только в строках с первой по десятую:

sed '1,10 s/0/1000/g' /etc/group

Переходим ещё ближе к регулярным выражениям, удалим все пустые строки или строки с комментариями из конфига Apache:

sed '/^#\|^$\| *#/d' /etc/apache2/apache2.conf

Под это регулярное выражение (адрес) подпадают все строки, которые начинаются с #, пустые, или начинаются с пробела, а за ним идет решетка. Регулярные выражения можно использовать и при замене. Например, заменим все вхождения p в начале строки на losst_p:

sed 's/[^p*]/losst_p/g' /etc/group

Если вам надо записать результат замены в обратно в файл можно использовать стандартный оператор перенаправления вывода > или утилиту tee. Например:

sed '/^#\|^$\| *#/d' /etc/apache2/apache2.conf | sudo tee /etc/apache2/apache2.conf

Также можно использовать опцию -i, тогда утилита не будет выполнять изменения в переданном ей файле:

sudo sed -i '/^#\|^$\| *#/d' /etc/apache2/apache2.conf

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

Выводы

Из этой статьи вы узнали что представляет из себя команда sed Linux. Как видите, это очень гибкий инструмент, который позволяет делать с текстом очень многое. Он сложный в освоении, но с помощью него очень удобно решать многие задачи редактирования конфигурационных файлов или фильтрации вывода.

Оцените статью

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (31 оценок, среднее: 3,16 из 5)
Загрузка...
Creative Commons License
Статья распространяется под лицензией Creative Commons ShareAlike 4.0 при копировании материала ссылка на источник обязательна .

13 комментариев к “Команда sed Linux”

  1. Да. Было время, когда и я тоже пользовался sed-ом... Причём несколько раз.
    Но потом понял -- мне проще и быстрее выполнять редактирование текста в обычном редакторе.

    Если работа происходит в графической консоли (у меня Debian, MATE), то проще запустить текстовый редактор pluma. Если же нужно выполнить редактирование удалённого файла (в смысле на другом компе), то это проще сделать с помощью nano или mcedit (из пакета mc). На крайняк скопировать удалённый файл к себе на комп, изменить и вернуть обратно. Но использовать sed-ом -- 🙁 ... смысл этого я что-то не очень понимаю. На минутчку! За последние лет 10 я его так ни разу по делу и не использовал, не было нужды прибегать именно к нему на фоне других редакторов текста.

    А никто случаем не заметил диссонанса на скриншотах в статье? С одной стороны -- мощный компьютер с мощным процессором и гигабайтами памяти, современной видеокартой с высоким разрешением и графический рабочий стол. А с другой -- какой-то маленький потоковый редактор, которому для его работы нужно совсем ничтожное количество ресурсов компа. Которому совсем не нужна графика рабочего стола. Который, чтобы правильно запустить в работу и получить результат, которому можно верить, -- нужно ещё вспомнить как это всё делается... Что мы делаем? Какой в этом смысл?

    Да, sed -- очень симпатичный и быстрый редактор. Я искренне извиняюсь, но я просто не вижу ему реальных применение. Разве что понастальгировать. Но это из области эмоций, а не технологий. Мир Линукса изменился сильно со времен, когда sed был актуален. Изменились инструменты. Изменился подход к решению задач.

    Ответить
    • sed - инструмент программиста, наиболее частая область применения - скрипты, используется обычно для автоматизации сложных деплойментов, предполагающих много рутины, чтобы ручками нужные файлы не редактировать, вся рутина выстраивается в сценарий, а потом скрипт просто исполняется на сервере. Желающие использовать его в командной строке, ну чо, пусть поупражняются, всё одно - польза и интеллектуальное развитие организма.

      Ответить
        • Занят в embedded разработке под arm, phytec и т.п. Частенько приходилось в загрузочных скриптах или сервисных скриптах задействовать sed для автоматического парсинга логов, конфигурационных параметров системы и т.п. Утилиту sed очень удобно применять, когда входные данные на лету требуется преобразовать к требуемому для последующей переработки виду. Где кроется гемор с регулярными выражениями, так это в случаях, когда требуется автоматическое сервисное обслуживание устройств в сети по ssh. При необходимости передачи вложенных скриптовых выражений, которые частично должны интерпретироваться как чистый текст с необходимостью использования символов экранирования, а частично как команды подстановки. У меня бывали случаи, когда использование одного экранирующего символа "\" в исходном выражении могло приводить к преобразованию его к "\\\" для передачи выражения по ssh, в отдельных случаях неявное поведение баша вообще не позволяло сделать корректное эквивалентное преобразование команд для передачи по ssh. Честно говоря, регулярные выражения мне нравятся ровно до тех пор, пока из них не требуется сформировать более менее сложную команду. Это чуть ли не единственная для шелла вещь из области "Использовал при написании в скрипте, а потом через пол-года не можешь вспомнить, что эта мешанина из спец. и экранирующих символов может значить" XD

          Ответить
          • Ага. И Вам тоже спасибо!
            Я задам, возможно, глупый вопрос -- а файлы, о которых Вы говорите -- загрузочные скрипты, логи и так далее -- они какие по размеру? Сколько строк или килобайт в среднем? Я просто не очень себе представляю.

            Ну и мой глупый вопрос -- а почему с этими файлами лучше работать с помощью sed, а не обрабатывать их в Perl или Python?

            Я совершенно не представляю специфики, поэтому могу спросить что-то не то. Извиняйте, если что.

  2. Сегодня пришлось заняться: пользователь удалил несколько писем из архива за 2019 год почты Mozilla Thunderbird. Их надо восстановить. В "Удаленные" это письма, почему-то, не попали. Фактически письма всё ещё находятся в файле 2019 размером 9 Гб.
    Задача: заменить все строки X-Mozilla-Status: 0009 на X-Mozilla-Status: 0001. mcedit даже на открытии такого файла уже "присел".
    И вот решение: sed -i 's/X-Mozilla-Status:\ 0009/X-Mozilla-Status:\ 00091/g' 2019. Пара минут и все удалённые письма восстановлены.

    Ответить
  3. Вы писали:"Также можно использовать опцию -i, тогда утилита не будет выполнять изменения в переданном ей файле:

    sudo sed -i '/^#\|^$\| *#/d' /etc/apache2/apache2.conf"

    Как раз в этом случае файл будет очищен от пустых строк. 🙂

    Ответить
  4. Вы написали: "Также можно использовать опцию -i, тогда утилита не будет выполнять изменения в переданном ей файле:

    sudo sed -i '/^#\|^$\| *#/d' /etc/apache2/apache2.conf".
    Эта команда, как раз, изменит содержание файла.

    Ответить
  5. В статье достаточно много неточностей это и
    -i[SUFFIX]
    --in-place[=SUFFIX]
    и
    -l N
    --line-length=N
    (длинна первой команды) и тд
    (не люблю писать ртфм но https://www.gnu.org/software/sed/manual/ )
    sed - полноценный язык , наверное , я мощнее ( для текста ) не встречал ( ну перл, конечно )

    Ответить
  6. > sed '/^#\|^$\| *#/d' /etc/apache2/apache2.conf | sudo tee /etc/apache2/apache2.conf

    Такой командой вы можете получить неиллюзорные проблемы вплоть до потери содержимого файла. Нельзя читать и писать в один и тот же файл в пределах одного пайпа. Есть несколько обходных путей: с помощью опции самого sed, временного файла или sponge.

    Ответить
  7. пишу sed 1p leaflet.osm.js
    или sed 17p leaflet.osm.js или sed 17,18p leaflet.osm.js
    он мне всё равно выдаёт один и тотже текст
    L.OSM = {};
    L.OSM = {};

    L.OSM.TileLayer = L.TileLayer.extend({
    options: {
    url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
    attribution: '© OpenStreetMap contributors'
    },

    initialize: function (options) {
    options = L.Util.setOptions(this, options);
    L.TileLayer.prototype.initialize.call(this, options.url);
    }
    });
    и т.д.
    это значит что в файле строки не пронумерованы и он выдаёт сразу весь текст?
    как мне в 17 строке заменить https://tile.openstreetmap.org/{z}/{x}/{y}.png
    на
    https://ip/tile/{z}/{x}/{y}.png
    ?

    Ответить

Оставьте комментарий