Поиск по сайту:

Как использовать команду sed в Linux


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

Сила сед

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

sed — это потоковый редактор, который работает с конвейерным вводом или текстовыми файлами. Однако у него нет интерфейса интерактивного текстового редактора. Скорее, вы даете ему инструкции, которым он должен следовать, пока он работает с текстом. Все это работает в Bash и других оболочках командной строки.

С помощью sed вы можете делать все следующее:

  • Выберите текст
  • Заменить текст
  • Добавить строки в текст
  • Удалить строки из текста
  • Изменить (или сохранить) исходный файл

Мы структурировали наши примеры, чтобы представить и продемонстрировать концепции, а не создавать самые краткие (и наименее доступные) команды sed. Однако функции сопоставления шаблонов и выделения текста в sed в значительной степени зависят от регулярных выражений (регулярных выражений). Вам понадобится некоторое знакомство с ними, чтобы получить максимальную отдачу от sed.

Простой пример

Во-первых, мы собираемся использовать echo, чтобы отправить некоторый текст в sed по конвейеру, и sed подставить часть текста. Для этого набираем следующее:

echo howtogonk | sed 's/gonk/geek/'

Команда echo отправляет «howtogonk» в sed, и применяется наше простое правило подстановки («s» означает подстановку). sed ищет во входном тексте вхождение первой строки и заменяет все совпадения второй.

Строка «gonk» заменяется на «geek», и новая строка печатается в окне терминала.

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

Выбор текста

Нам понадобится текстовый файл для наших примеров. Мы будем использовать тот, который содержит подборку стихов из эпической поэмы Сэмюэля Тейлора Кольриджа «Иней древнего мореплавателя».

Мы вводим следующее, чтобы взглянуть на это с помощью less:

less coleridge.txt

Чтобы выбрать некоторые строки из файла, мы предоставляем начальную и конечную строки диапазона, который мы хотим выбрать. Одно число выбирает эту строку.

Чтобы извлечь строки с первой по четвертую, мы набираем эту команду:

sed -n '1,4p' coleridge.txt

Обратите внимание на запятую между 1 и 4. p означает «печатать совпадающие строки». По умолчанию sed выводит все строки. Мы увидели бы весь текст в файле с совпадающими строками, напечатанными дважды. Чтобы предотвратить это, мы будем использовать параметр -n (quiet) для подавления несовпадающего текста.

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

sed -n '6,9p' coleridge.txt

Мы можем использовать параметр -e (выражение), чтобы сделать множественный выбор. С двумя выражениями мы можем выбрать два стиха, например:

sed -n -e '1,4p' -e '31,34p' coleridge.txt

Если мы уменьшим первое число во втором выражении, мы можем вставить пробел между двумя стихами. Набираем следующее:

sed -n -e '1,4p' -e '30,34p' coleridge.txt

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

Первая цифра обозначает стартовую линию. Второе число сообщает sed, какие строки после начальной строки мы хотим видеть. Цифра 2 означает каждую вторую строку, 3 — каждую третью строку и так далее.

Набираем следующее:

sed -n '1~2p' coleridge.txt

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

Знак вставки (^) обозначает начало строки. Мы заключим наш поисковый запрос в косую черту (/). Мы также добавляем пробел после «И», чтобы такие слова, как «Android», не были включены в результат.

Поначалу чтение скриптов sed может быть немного сложным. /p означает «печать», как и в командах, которые мы использовали выше. Однако в следующей команде ей предшествует косая черта:

sed -n '/^And /p' coleridge.txt

Три строки, начинающиеся с «И», извлекаются из файла и отображаются для нас.

Замены

В нашем первом примере мы показали вам следующий базовый формат замены sed:

echo howtogonk | sed 's/gonk/geek/'

s сообщает sed, что это замена. Первая строка — это шаблон поиска, а вторая — текст, которым мы хотим заменить этот совпадающий текст. Конечно, как и во всем, что связано с Linux, дьявол кроется в деталях.

Мы вводим следующее, чтобы заменить все вхождения «день» на «неделя» и дать моряку и альбатросу больше времени для связи:

sed -n 's/day/week/p' coleridge.txt

В первой строке изменяется только второе вхождение слова день. Это связано с тем, что sed останавливается после первого совпадения в строке. Мы должны добавить «g» в конце выражения, как показано ниже, чтобы выполнить глобальный поиск и обработать все совпадения в каждой строке:

sed -n 's/day/week/gp' coleridge.txt

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

Мы вводим следующее, добавляя i к команде в конце выражения, чтобы указать нечувствительность к регистру:

sed -n 's/day/week/gip' coleridge.txt

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

Например, если мы заключаем символы в квадратные скобки ([]), они интерпретируются как «любой символ из этого списка символов».

Мы вводим следующее и включаем «D» и «d» в группу, чтобы убедиться, что она соответствует как «Day», так и «day»:

sed -n 's/[Dd]ay/week/gp' coleridge.txt

Мы также можем ограничить замены разделами файла. Допустим, наш файл содержит странный пробел в первом куплете. Мы можем использовать следующую знакомую команду, чтобы увидеть первый стих:

sed -n '1,4p' coleridge.txt

Мы найдем два пробела и заменим их одним. Мы сделаем это глобально, чтобы действие повторялось по всей строке. Для ясности: шаблон поиска — пробел, звездочка пробела (*), а строка подстановки — один пробел. 1,4 ограничивает замену первыми четырьмя строками файла.

Объединяем все это в следующую команду:

sed -n '1,4 s/  */ /gp' coleridge.txt

Это прекрасно работает! Здесь важна схема поиска. Звездочка (*) представляет ноль или более предшествующих символов, то есть пробел. Таким образом, шаблон поиска ищет строки из одного пробела или более.

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

Если мы введем следующее и сократим шаблон поиска до одного пробела, вы сразу поймете, почему мы должны включать два пробела:

sed -n '1,4 s/ */ /gp' coleridge.txt

Поскольку звездочка соответствует нулю или более предшествующих символов, она видит каждый символ, который не является пробелом, как «нулевой пробел» и применяет к нему замену.

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

Мы вводим следующее, используя -e (выражение), которое мы использовали ранее, что позволяет нам делать две или более замены одновременно:

sed -n -e 's/motion/flutter/gip' -e 's/ocean/gutter/gip' coleridge.txt

Мы можем добиться того же результата, если используем точку с запятой (;) для разделения двух выражений, например:

sed -n 's/motion/flutter/gip;s/ocean/gutter/gip' coleridge.txt

Когда мы заменили «день» на «неделю» в следующей команде, экземпляр «дня» в выражении «хорошо день» также был заменен местами:

sed -n 's/[Dd]ay/week/gp' coleridge.txt

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

Мы вводим следующее, чтобы сделать наш шаблон соответствия словом «после»:

sed -n '/after/ s/[Dd]ay/week/gp' coleridge.txt

Это дает нам ответ, который мы хотим.

Более сложные замены

Давайте дадим Кольриджу передышку и воспользуемся sed для извлечения имен из файла etc/passwd.

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

Вы должны заключить подвыражение в круглые скобки [()], чтобы это работало. Перед круглыми скобками должна стоять обратная косая черта (\), чтобы они не воспринимались как обычные символы.

Для этого вы должны ввести следующее:

sed 's/\([^:]*\).*/\1/' /etc/passwd

Давайте разберем это:

  • sed s/: команда sed и начало выражения подстановки.
  • \(: Открывающая скобка [(], заключающая подвыражение, перед которой ставится обратная косая черта (\ ).
  • [^:]*: Первое подвыражение поискового запроса содержит группу в квадратных скобках. Знак вставки (^) означает «не» при использовании в группе. Группа означает, что любой символ, кроме двоеточия (:), будет принят в качестве совпадения.
  • \): закрывающая скобка [)] с предшествующей обратной косой чертой (\).
  • .*: это второе поисковое подвыражение означает «любой символ и любое их количество».
  • /\1: Подстановочная часть выражения содержит 1, которому предшествует обратная косая черта (\) . Представляет собой текст, соответствующий первому подвыражению.
  • /: закрывающая косая черта (/) и одинарная кавычка () завершают sed команда.

Все это означает, что мы будем искать любую строку символов, не содержащую двоеточие (:), которая будет первым экземпляром совпадающего текста. Затем мы ищем что-нибудь еще в этой строке, которая будет вторым экземпляром совпадающего текста. Мы собираемся заменить всю строку текстом, соответствующим первому подвыражению.

Каждая строка в файле /etc/passwd начинается с имени пользователя, заканчивающегося двоеточием. Мы сопоставляем все до первого двоеточия, а затем подставляем это значение для всей строки. Итак, мы изолировали имена пользователей.

Затем мы заключим второе подвыражение в круглые скобки [()], чтобы мы могли также ссылаться на него по номеру. Мы также заменим \1 на \2. Теперь наша команда заменит всю строку всем от первого двоеточия (:) до конца строки.

Набираем следующее:

sed 's/\([^:]*\)\(.*\)/\2/' /etc/passwd

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

Теперь давайте рассмотрим быстрый и простой способ сделать это.

Наш поисковый запрос идет от первого двоеточия (:) до конца строки. Поскольку наше выражение подстановки пусто (//), мы не будем ничем заменять совпавший текст.

Итак, набираем следующее, обрезав все от первого двоеточия (:) до конца строки, оставив только имена пользователей:

sed 's/:.*//" /etc/passwd

Давайте рассмотрим пример, в котором мы ссылаемся на первое и второе совпадения в одной и той же команде.

У нас есть файл запятых (,), разделяющих имя и фамилию. Мы хотим перечислить их как «фамилия, имя». Мы можем использовать cat, как показано ниже, чтобы увидеть, что находится в файле:

cat geeks.txt

Как и многие другие команды sed, следующая поначалу может показаться непонятной:

sed 's/^\(.*\),\(.*\)$/\2,\1 /g' geeks.txt

Это команда подстановки, как и другие, которые мы использовали, и шаблон поиска довольно прост. Мы разберем это ниже:

  • sed s/: обычная команда замены.
  • ^: Поскольку знак вставки не находится в группе ([]), он означает «Начало строки».
  • \(.*\),: первое подвыражение — любое количество любых символов. Он заключен в круглые скобки [()], каждой из которых предшествует обратная косая черта (\), поэтому мы можем ссылаться на нее по номеру. Весь наш шаблон поиска до сих пор переводится как поиск от начала строки до первой запятой (,) для любого количества любых символов.
  • \(.*\): Следующее подвыражение (снова) представляет собой любое количество любых символов. Он также заключен в круглые скобки [()], которым предшествует обратная косая черта (\), поэтому мы можем сослаться на соответствующий текст по номеру.
  • $/: Знак доллара ($) представляет собой конец строки и позволяет продолжить поиск до конца строки. линия. Мы использовали это просто, чтобы ввести знак доллара. Здесь он нам не особо нужен, так как в этом случае звездочка (*) будет стоять в конце строки. Косая черта (/) завершает раздел шаблона поиска.
  • \2,\1 /g: Поскольку мы заключили два наших подвыражения в круглые скобки, мы можем ссылаться на них обоих по номерам. Поскольку мы хотим изменить порядок, мы вводим их как второе совпадение, первое совпадение. Перед числами должна стоять обратная косая черта (\).
  • /g: это позволяет нашей команде работать глобально над каждой строкой.
  • geeks.txt: файл, над которым мы работаем.

Вы также можете использовать команду «Вырезать» (c), чтобы заменить целые строки, соответствующие вашему шаблону поиска. Мы вводим следующее, чтобы найти строку со словом «шея» и заменить ее новой строкой текста:

sed '/neck/c Around my wrist was strung' coleridge.txt

Наша новая строка теперь появляется в нижней части нашего экстракта.

Вставка линий и текста

Мы также можем вставить новые строки и текст в наш файл. Чтобы вставить новые строки после любых совпадающих, мы будем использовать команду «Добавить» (a).

Вот файл, с которым мы будем работать:

кот вундеркинд.txt

Мы пронумеровали строки, чтобы вам было легче следовать.

Мы вводим следующее для поиска строк, содержащих слово «Он», и вставляем новую строку под ними:

sed '/He/a --> Inserted!' geeks.txt

Мы вводим следующее и включаем команду «Вставить» (i), чтобы вставить новую строку над теми, которые содержат соответствующий текст:

sed '/He/i --> Inserted!' geeks.txt

Мы можем использовать амперсанд (&), который представляет исходный совпадающий текст, чтобы добавить новый текст в совпадающую строку. \1 , \2 и т. д. представляют совпадающие подвыражения.

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

Чтобы сделать все это, мы набираем следующее:

sed 's/.*/--> Inserted &/' geeks.txt

Мы вводим следующее, включая команду G, которая добавит пустую строку между каждой строкой:

sed 'G' geeks.txt

Если вы хотите добавить две или более пустых строки, вы можете использовать G;GG;G;G и т. д.

Удаление линий

Команда Удалить (d) удаляет строки, соответствующие шаблону поиска, или те, которые указаны номерами строк или диапазонами.

Например, чтобы удалить третью строку, мы должны ввести следующее:

sed '3d' geeks.txt

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

sed '4,5d' geeks.txt

Чтобы удалить строки за пределами диапазона, мы используем восклицательный знак (!), как показано ниже:

sed '6,7!d' geeks.txt

Сохранение ваших изменений

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

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

Для некоторого спокойствия sed может создать резервную копию исходного файла перед выполнением своей команды.

Вы можете использовать параметр На месте (-i), чтобы указать sed записать изменения в исходный файл, но если вы добавите к нему расширение файла, sed создаст резервную копию исходного файла в новый. Он будет иметь то же имя, что и исходный файл, но с новым расширением.

Для демонстрации мы найдем все строки, содержащие слово «Он», и удалим их. Мы также создадим резервную копию нашего исходного файла в новый, используя расширение BAK.

Чтобы сделать все это, мы набираем следующее:

sed -i'.bak' '/^.*He.*$/d' geeks.txt

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

cat geeks.txt.bak

Мы также можем ввести следующее, чтобы перенаправить вывод в новый файл и добиться аналогичного результата:

sed -i'.bak' '/^.*He.*$/d' geeks.txt > new_geeks.txt

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

cat new_geeks.txt

Пройдя все это

Как вы, наверное, заметили, даже это краткое руководство по sed довольно длинное. В этой команде много всего, и вы можете сделать с ней еще больше.

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

RELATED: Best Linux Laptops for Developers and Enthusiasts