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

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

Сила sed

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

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

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

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

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

СВЯЗАННЫЕ: Как использовать регулярные выражения (регулярные выражения) в Linux

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

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

эхо howtogonk | sed 's / гонк / компьютерщик /'

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

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

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

Выбор текста

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

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

меньше coleridge.txt

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

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

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

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

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

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 '/ ^ И / p' coleridge.txt

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

Выполнение замен

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

эхо howtogonk | sed 's / гонк / компьютерщик /'

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

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

sed -n 's / день / неделя / p' coleridge.txt

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

sed -n 's / день / неделя / gp' coleridge.txt

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

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

sed -n 's / день / неделя / gip' coleridge.txt

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

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

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

sed -n 's / [Дд] год / неделя / 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 / движение / flutter / gip' -e 's / ocean / gutter / gip' coleridge.txt

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

sed -n 's / движение / flutter / gip; s / ocean / gutter / gip' coleridge.txt

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

sed -n 's / [Дд] год / неделя / gp' coleridge.txt

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

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

sed -n '/ после / s / [Дд] год / неделя / 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, как показано ниже, чтобы увидеть, что находится в файле:

кошка geeks.txt

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

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

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

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

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

sed '/ Neck / c Вокруг моего запястья был натянут' coleridge.txt

Наша новая строка теперь появляется внизу отрывка.

Вставка строк и текста

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

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

кошка geeks.txt

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

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

sed '/ He / a -> Вставлено!' geeks.txt

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

sed '/ He / i -> Вставлено!' geeks.txt

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

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

Для всего этого набираем следующее:

sed 's /.*/--> Вставлен & /' 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

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

кот geeks.txt.bak

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

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

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

кот new_geeks.txt

Получив все это

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

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