sed
Введение
Это статья про SED.
Вам могут пригодится также статьи
AWK
и
GREP
Примеры я показываю в
Bash под Windows 10
или в
Bash
в
Linux
.
Основные команды Sed
Для того чтобы применить SED достаточно ввести в командную строку
echo ice | sed s/ice/fire/
Результат:
fire
Обратите внимание на то, что использовать
/ не обязательно.
Вы можете после s поставить какой-то другой символ, например
: или , или
|
Результат будет тем же, главное, чтобы все три разделителя были одинаковыми
и сам символ был без дополнительных смыслов.
echo mice | sed s/m/r/
echo mice | sed s,m,r,
echo mice | sed s:m:r:
rice
rice
rice
Если вы выбрали |, то команду нужно взять в кавычки - у | есть особая роль в bash - pipeline
echo mice | sed 's|m|r|'
rice
Если вы редактируете пути до файлов (а они содержат /)
то это как раз тот случай, когда удобно выбрать другой разделитель
Например, нужно заменить /bin/bash на /bin/sh
Намного удобнее использовать @ как разделитель чем
экранировать
каждый слеш.
Сравните две идентичные команды
sed 's@/bin/bash@/bin/sh@' /etc/passwd
sed 's/\/bin\/bash/\/bin\/sh/' /etc/passwd
Удалить что-то из файла
За удаление отвечает опция d про неё вы можете прочитать отдельную статью sed d
Также можно удалять заменой на пустое место
s/что-то//
И удалять с помощью других опций, например, q
Удалить всё, что слева |
Удалить всё, что справа |
Удаление переходов на новую строку |
Обрезать файл - Удалить всё начиная с определённой строки |
Удалить всё между скобками |
Сделать замену
За замену отвечает опция s про неё вы можете прочитать отдельную статью sed s - substitute
Замена слова в файле |
Замена слова в нескольких файлах одновременно |
Замена только в определённых строках |
Добавить отступы |
Заменить пустые строки |
Изменить начало строки |
Изменить значение в JSON файле |
Экранирование символов в sed
Специальные символы экранируются с помощью \
Что включать в специальные символы зависит от того, какой
sed вы используете, но $.*[\^ а также пробелы и кавычки
советую экранировать всегда.
Пробел также можно заменять на \s
. в регулярных выражениях обозначает один любой символ кроме начала новой строки \n
поэтому, если вы хотите написать url используйте \
heihei\.ru
Пример экранирования точек и кавычек для смены локали в
CentOS
можете изучить
здесь
Предположим, что есть файл
input.txt
следующего содержания
Here is a String / it has a Name
Here is an Integer / it has a Name
Here is a Float it / has a Name
Мы хотим отбросить всё, что находится левее /a, включая /a, и записать в файл.
sed 's/^.*/a//' > output.txt
В результате получим ошибку
-e expression #1, char 15: unknown option to `s'
Чтобы команда заработала нужно добавить \ перед /
sed 's/^.*\/a//' > output.txt
Результат:
Here is a String
Here is an Integer
Here is a Float
Экранирование пробелов может пригодиться при замене одной фразы на другую
Чтобы в скрипте
sites.sh
из директории
/opt/andrei/scripts/ заменить фразу
Bike website topbicycle.ru
на
Travel website heihei.ru
нужно выполнить
sed -i s/Bike\ website\ topbicycle.ru/Travel\ website\ heihei.ru/ /opt/andrei/scripts/sites.sh
Два условия одновременно в Sed
Предположим, что у нас есть файл input.txt следующего содержания
Here is a String /b it has a Name
Here is an Integer /b it has a Name
Here is a Float /b it has a Name
Мы хотим отбросить всё, что находится левее /b, включая /b, и всё, что правее
has.
Таким образом, в каждой строчке должно остаться только слово it.
Нужно учесть необходимость экранирования специального символа / а также мы хотим
направить вывод в файл.
sed 's/^.*\/b// ; s/has.*//' input.txt > output.txt
Результат:
it
it
it
Получить диапазон строк
В случае, когда Вы работаете с большими файлами, например с логами, часто бывает нужно
получить только определённые строки, например, в момент появления бага.
Копировать из UI командной строки не всегда удобно, но если Вы примерно представляете
диапазон нужных строк - можно скопировать только их и записать в отдельный файл.
Например, Вам нужны строки с 9570 по 9721
sed -n '9570,9721p;9722q' project-2019-10-03.log > bugFound.txt
Заменить всё между определёнными символами
Удалить всё что находится между квадратными скобками включая скобки
sed 's/\[.*\]//' input.txt > output.txt
Создать функцию
Чтобы каждый раз не вспоминать команды sed можно создать функцию
Возьмём команду, которая удаляет комментарии и пустые строки из предыдущего примера и
запишем как функцию clean_file.
Первым делом в коносли нужно написать в терминале function clean_file {
и нажать Enter
Затем ввести выражение sed -i '/^#/d ; /^$/d' $1
$1 означает, что функция будет принимать один аргумент. Это, конечно, будет название файла.
Затем нужно снова нажать Enter и в новой строке написать } и нажать Enter ещё раз
$ function clean_file { > sed -i '/^#/d;/^$/d' $1 > }
Убедитесь, что файл содержит комментарии и пустые строки. Если нет - создайте для чистоты эксперимента.
cat websites
# Travel https://www.heihei.ru # Bicycles https://www.topbicycle.ru # IT https://www.eth1.ru
clean_file websites
cat websites
https://www.heihei.ru https://www.topbicycle.ru https://www.eth1.ru
Отбросить всё, что левее определённого слова
Предположим, что у нас есть файл input.txt следующего содержания
Here is a String it has a Name
Here is an Integer it has a Name
Here is a Float it has a Name
Мы хотим отбросить всё, что находится левее слова it, включая слово it, и записать в файл.
sed 's/^.*it//' input.txt > output.txt
^ означает, что мы стартуем с начала строки Результат:
has a Name
has a Name
has a Name
Для доступности объясню синтаксис сравнив две команды. Посмотрите внимательно, когда мы заменяем
слово Here на There.
There находится между двумя слэшами. Раскрашу их для наглядности в зелёный и красный.
sed 's/Here/There/'
А когда мы хотим удалить что-то, мы сначала описываем, что мы хотим удалить. Например, всё от
начала строки до слова it.
Теперь в правой части условия, где раньше была величина на замену, мы
ничего не пишем, т.е. заменяем на пустое место. Надеюсь, логика понятна.
sed 's/^.*it//' > output.txt
Отбросить всё, что правее определённого слова
Предположим, что у нас есть файл input.txt следующего содержания
Here is a String / it has a Name
Here is an Integer / it has a Name
Here is a Float / it has a Name
Мы хотим отбросить всё, что находится правее слова is, включая слово is, и записать в файл.
sed 's/is.*//' > output.txt
Результат:
Here
Here
Here
Удаление переходов на новую строку
sed ':a;N;$!ba;s/\n//g' file ;
Удалить всё после определённой строки
Допустим Вы хотите удалить все строки после третьей
sed 3q input.txt > output.txt
РЕКЛАМА от Яндекса. Может быть недоступна в вашем регионе
Конец рекламы. Если там пусто считайте это рекламой моей телеги