Компиляция из двух смежных статей на тему использования команды
sed
для редактирования текстовых файлов, включая различные варианты поиска и замены шаблонов, а также всевозможные операции со строками. Идею к публикации этого гайда подал участник nronnie в комментарии к предыдущей статье, посвящённой работе с Bash.SED – это потоковый редактор текста (от stream editor), c помощью которого можно выполнять с файлами множество операций вроде поиска и замены, вставки или удаления. При этом чаще всего он используется именно для поиска и замены.
SED позволяет редактировать файлы, не открывая, что существенно ускоряет работу, чем при использовании того же vi. Помимо этого, SED поддерживает регулярные выражения, с помощью которых можно выполнять сложное сопоставление шаблонов.
Общий синтаксис команды
sed
выглядит так:sed OPTIONS... [SCRIPT] [INPUTFILE...]
Сами же варианты её использования мы рассмотрим на примере следующего отрывка текста:
$cat > geekfile.txt
unix is great os. unix is opensource. unix is free os.
learn operating system.
unix linux which one you choose.
unix is easy to learn.unix is a multiuser os.Learn unix .unix is a powerful.
Примеры команд
1. Замена заданного шаблона
Следующая команда заменит в целевом файле вхождения слова
unix
на linux
:$sed 's/unix/linux/' geekfile.txt
Вывод:
linux is great os. unix is opensource. unix is free os.
learn operating system.
linux linux which one you choose.
linux is easy to learn.unix is a multiuser os.Learn unix .unix is a powerful.
Здесь
s
обозначает операцию замены, а прямые слэши выступают разделителями. В качестве искомого шаблона используется unix
, а в качестве его замены linux
.По умолчанию команда
sed
заменяет первое вхождение шаблона в каждой строке, не затрагивая второе, третье и т.д.2. Замена n-ого вхождения шаблона в строке
Вхождения, которые нужно заменить, обозначаются с помощью флагов
/1
, /2
и т.д. К примеру, следующая команда заменит в каждой строке второе вхождение:$sed 's/unix/linux/2' geekfile.txt
Вывод:
unix is great os. linux is opensource. unix is free os.
learn operating system.
unix linux which one you choose.
unix is easy to learn.linux is a multiuser os.Learn unix .unix is a powerful.
3. Замена всех вхождений шаблона в файле
Дя замены всех без исключения вхождений заданного шаблона используется глобальный флаг
/g
:$sed 's/unix/linux/g' geekfile.txt
Вывод:
linux is great os. linux is opensource. linux is free os.
learn operating system.
linux linux which one you choose.
linux is easy to learn.linux is a multiuser os.Learn linux .linux is a powerful.
4. Замена всех вхождений шаблона в строке начиная с n-ого
Для этого номер вхождения, с которого нужно начать, сопровождается флагом
g
. Следующая команда заменит в каждой строке третье, четвёртое и т.д. вхождения слова unix
на слово linux
:$sed 's/unix/linux/3g' geekfile.txt
Вывод:
unix is great os. unix is opensource. linux is free os.
learn operating system.
unix linux which one you choose.
unix is easy to learn.unix is a multiuser os.Learn linux .linux is a powerful.
5. Заключение первых символов слов в скобки
Следующая команда заключит в скобки первый символ каждого слова:
$ echo "Welcome To The Geek Stuff" | sed 's/\(\b[A-Z]\)/\(\1\)/g'
Вывод:
(W)elcome (T)o (T)he (G)eek (S)tuff
6. Замена шаблона в конкретной строке
Можно ограничить выполнение команды
sed
нужной строкой:$sed '3 s/unix/linux/' geekfile.txt
Вывод:
unix is great os. unix is opensource. unix is free os.
learn operating system.
linux linux which one you choose.
unix is easy to learn.unix is a multiuser os.Learn unix .unix is a powerful.
Вышеприведённая команда заменяет заданное слово только в третьей строке.
7. Дублирование изменяемых строк
При добавлении флага
/p
команда выведет в терминал строки, где производится замена. Строки, в которых искомый шаблон отсутствует, не дублируются.$sed 's/unix/linux/p' geekfile.txt
Вывод:
linux is great os. unix is opensource. unix is free os.
linux is great os. unix is opensource. unix is free os.
learn operating system.
linux linux which one you choose.
linux linux which one you choose.
linux is easy to learn.unix is a multiuser os.Learn unix .unix is a powerful.
linux is easy to learn.unix is a multiuser os.Learn unix .unix is a powerful.
8. Вывод только строк с заменой
Если рядом с флагом
/p
добавить ключ -n
, в терминале отобразятся только строки, где выполнялась замена. В данном случае -n
отключает дублирующее поведение флага /p
, поэтому строки с заменой выводятся по одному разу.$sed -n 's/unix/linux/p' geekfile.txt
Вывод:
linux is great os. unix is opensource. unix is free os.
linux linux which one you choose.
linux is easy to learn.unix is a multiuser os.Learn unix .unix is a powerful.
Если использовать только
-n
, исключив /p
, вывод команда не произведёт.9. Замена шаблона в указанном диапазоне строк
sed
позволяет указывать диапазон строк, в которых требуется заменить определённый шаблон:$sed '1,3 s/unix/linux/' geekfile.txt
Вывод:
linux is great os. unix is opensource. unix is free os.
learn operating system.
linux linux which one you choose.
unix is easy to learn.unix is a multiuser os.Learn unix .unix is a powerful.
Здесь
sed
производит замену в строках с 1 по 3. А вот ещё один пример:$sed '2,$ s/unix/linux/' geekfile.txt
Вывод:
unix is great os. unix is opensource. unix is free os.
learn operating system.
linux linux which one you choose.
linux is easy to learn.unix is a multiuser os.Learn unix .unix is a powerful
Здесь
$
указывает на последнюю строку файла, в связи с чем sed
заменяет первые вхождения шаблона, начиная со второй и заканчивая ей.10. Удаление строк из файла
С помощью
sed
также можно удалять строки из заданного файла:10.1 Удаление n-ой строки:
Синтаксис:
$ sed 'nd' filename.txt
Пример:
$ sed '5d' filename.txt
10.2 Удаление последней строки:
Синтаксис:
$ sed '$d' filename.txt
10.3 Удаление строк с x> по y:
Синтаксис:
$ sed 'x,yd' filename.txt
Пример:
$ sed '3,6d' filename.txt
10.4 Удаление строк с n-ой до последней:
Синтаксис:
$ sed 'n,$d' filename.txt
Пример:
$ sed '12,$d' filename.txt
10.5 Удаление текста, соответствующего шаблону:
Синтаксис:
$ sed '/pattern/d' filename.txt
Пример:
$ sed '/abc/d' filename.txt
Примеры команд (продолжение)
Во второй части мы разберём ещё одну серию операций с командой
sed
на примере уже другого файла, a.txt. Чтобы излишне не растягивать статью, вывод команд далее приводится не будет, так что для лучшего понимания можете самостоятельно попрактиковаться, создав такой же файл с аналогичным содержимым.[root@rhel7 ~]# cat a.txt
life isn't meant to be easy, life is meant to be lived.
Try to learn & understand something new everyday in life.
Respect everyone & most important love everyone.
Don’t hesitate to ask for love & don’t hesitate to show love too.
Life is too short to be shy.
In life, experience will help you differentiating right from wrong.
Добавление/удаление пустых строк в файле
1. Вставить после каждой текстовой строки одну пустую:
[root@rhel7 ~]# sed G a.txt
2. Вставить две пустые строки:
[root@rhel7 ~]# sed 'G;G' a.txt
3. Удалить все пустые строки и вставить по одной после каждой текстовой:
[root@rhel7 ~]# sed '/^$/d;G' a.txt
4. Вставить пустую строку над каждой, содержащей
love
:[root@rhel7 ~]# sed '/love/{x;p;x;}' a.txt
5. Вставить пустую строку после каждой, содержащей
love
: [root@rhel7 ~]# sed '/love/G' a.txt
6. Вставить 5 пробелов слева от каждой строки:
[root@rhel7 ~]# sed 's/^/ /' a.txt
Нумерация строк
1. Пронумеровать каждую строку файла (с левым выравниванием).
В этой команде символ
=
используется для нумерации строки, а флаг \t
для табулирования между номером и предложением:Пример:
[root@rhel7 ~]# sed = a.txt | sed 'N;s/\n/\t/'
2. Пронумеровать каждую строку файла (число слева, выравнивание по правому краю).
Эта команда похожа на
`cat -n filename`
:Пример:
[root@rhel7 ~]# sed = a.txt | sed 'N; s/^/ /; s/ *\(.\{4,\}\)\n/\1 /'
3. Пронумеровать каждую непустую строку файла:
Пример:
[root@rhel7 ~]# sed '/./=' a.txt | sed '/./N; s/\n/ /'
Удаление строк
1. Удалить конкретную строку:
Синтаксис:
sed ‘nd’ filename
Пример:
[root@rhel7 ~]# sed '5d' a.txt
2. Удалить последнюю строку:
Синтаксис:
sed ‘$d’ filename
3. Удалить строки с
x
по y
:Синтаксис:
sed ‘x,yd’ filename
Пример:
[root@rhel7 ~]# sed '3,5d' a.txt
4. Удалить строки с n-ой до последней:
Синтаксис:
sed ‘n,$d’ filename
Пример:
[root@rhel7 ~]# sed '2,$d' a.txt
5. Удалить строку, содержащую шаблон:
Синтаксис:
sed ‘/pattern/d’ filename
Пример:
[root@rhel7 ~]# sed '/life/d' a.txt
6. Удалить каждую вторую строку начиная с n-ой:
Синтаксис:
sed ‘n~2d’ filename
Пример:
[root@rhel7 ~]# sed '3~2d' a.txt
7. Удалить строки, содержащие шаблон, и по две строки после них:
Синтаксис:
sed ‘/pattern/,+2d’ filename
Пример:
[root@rhel7 ~]# sed '/easy/,+2d' a.txt
8. Удалить пустые строки:
Пример:
[root@rhel7 ~]# sed '/^$/d' a.txt
9. Удалить пустые строки или начинающиеся с
#
:Пример:
[root@rhel7 ~]# sed -i '/^#/d;/^$/d' a.txt
Просмотр/вывод строк
Для просмотра содержимого файла мы используем команду
cat
, а его начало и конец просматриваем с помощью утилит head
и tail
. Но что, если нас интересует некий участок в середине файла? В таком случае можно снова задействовать sed
.1. Просмотреть файл со строки x по y:
Синтаксис:
sed -n ‘x,yp’ filename
Пример:
[root@rhel7 ~]# sed -n '2,5p' a.txt
2. Просмотреть весь файл, за исключением заданного диапазона:
Синтаксис:
sed ‘x,yd’ filename
Пример:
[root@rhel7 ~]# sed '2,4d' a.txt
3. Вывести n-ую строку файла:
Синтаксис:
sed -n ‘address’p filename
Пример:
[root@rhel7 ~]# sed -n '4'p a.txt
4. Вывести строки с x по y:
Синтаксис:
sed -n ‘x,y’p filename
Пример:
[root@rhel7 ~]# sed -n '4,6'p a.txt
5. Вывести только последнюю строку:
Синтаксис:
sed -n ‘$’p filename
6. Вывести с n-ой строки до последней:
Синтаксис:
sed -n ‘n,$p’ filename
Пример:
[root@rhel7 ~]# sed -n '3,$'p a.txt
7. Вывести строки, содержащие указанный шаблон:
Синтаксис:
sed -n /pattern/p filename
Пример:
[root@rhel7 ~]# sed -n /every/p a.txt
8. Вывести строки начиная с первой, где обнаружен шаблон, и до строки x:
Синтаксис:
sed -n ‘/pattern/,xp’ filename
Пример:
[root@rhel7 ~]# sed -n '/everyone/,5p' a.txt
В данном случае первое вхождение
everyone
содержится в строке 3, значит в терминале отобразятся строки с 3 по 5. Если нужно вывести файл до конца, используйте вместо 5 символ $
.9. Вывести строки с x и до строки, содержащей шаблон. Если шаблон не обнаруживается, выводится файл до конца:
Синтаксис:
sed -n ‘x,/pattern/p’ filename
Пример:
sed -n '1,/everyone/p' a.txt
10. Вывести все строки, содержащие шаблон, включая следующие за каждой из них x строк:
Синтаксис:
sed -n ‘/pattern/,+xp’ filename
Пример:
sed -n '/learn/,+2p' a.txt
Замена с помощью команды sed (дополнение)
Ниже приводится небольшой список операций, дополняющий перечисленные ранее.
1. Два способа замены шаблона, игнорируя регистр:
1.1 Использовать флаг
/i
:Синтаксис:
sed ‘s/old_pattern/new_pattern/i’ filename
Пример:
[root@rhel7 ~]# sed 's/life/Love/i' a.txt
1.2 Использовать регулярные выражения:
Пример:
[root@rhel7 ~]# sed 's/[Ll]ife/Love/g' a.txt
2. Замена нескольких пробелов одним:
Пример: [root@rhel7 clang]# sed 's/ */ /g' filename
3. Замена шаблона, сопровождающего другой шаблон:
Синтаксис:
sed ‘/followed_pattern/ s/old_pattern/new_pattern/’ filename
Пример:
[root@rhel7 ~]# sed '/is/ s/live/love/' a.txt
10. Замена шаблона другим шаблоном, за исключением строки n:
Синтаксис:
sed ‘n!s/old_pattern/new_pattern/’ filename
Пример:
[root@rhel7 ~]# sed -i '5!s/life/love/' a.txt
Комментарии (9)
odiemius
27.05.2022 17:53+1Изучить sed несложно: поредактируйте файлы из консоли, напишите программку на любом ЯП, но используя sed в качестве редактора. По вкусу можно вместо sed использовать при этом ed. После этого команды просто автоматически будут от зубов отскакивать.
А для непосвященных - МАГИЯ, да :)
впрочем как и от vi, когда в нём умеешь работать (с буферами copy-paste и прочим), когда в деталях знаешь нюансы отличий команд vim (который под Linux обычно ставят как vi) от nvi (который ставится по умолчанию во FreeBSD)...
event1
27.05.2022 18:30+33. Удалить строки с
x
поy
:Синтаксис:
sed ‘x,yd’ filename
Пример:
[root@rhel7 ~]# sed '3,5d' a.txt
2. Просмотреть весь файл, за исключением заданного диапазона:
Синтаксис:
sed ‘x,yd’ filename
Пример:
[root@rhel7 ~]# sed '2,4d' a.txt
Чёртова магия! Одна команда и просматривает строки и удаляет их. Статья была бы лучше, если бы вначале набросали общий синтаксис. Он очень простой, в один абзац можно уложиться.
1.1 Использовать флаг
/i
:Это расширение GNU, кстати
RumataEstora
28.05.2022 10:23+1$ echo "Welcome To The Geek Stuff" | sed 's/\(\b[A-Z]\)/\(\1\)/g'
Код выше можно сократить до
$ echo "Welcome To The Geek Stuff" | sed 's/\b[A-Z]/(&)/g'
Еще примеры
показать только первую и последнюю строки (комбинация
head -1
/tail -1
)sed -n '1p;$p'
Объединить все строки (аналог
paste -sd ' '
)sed ":a;N;s/\n/ /;ta"
Объединить строки попарно
sed "N;s/\n/ /"
Своп каждой пары строк
sed -n '$p;h;n;G;p'
Сравнить две строки и вывести общий совпадающий фрагмент (начало строк)
sed -n 'N;s/\(.*\).*\n\1.*/\1/p'
nameantonch
Объясните пожалуйста др. пример:
Грубый эмулятор grep:
Не могу понять что в данном примере делает знак "/s" который вроде как для замены(в данном случае возможно просто заставляет выступить $1 в качестве фильтра) и знак начала строки "^"?
krovlya
/некоесловодляпоиска/ - первая конструкция, ищет по шаблону
s|^|имяфайладляпоиска: |p - вторая конструкция, меняет в найденной строке начало строки на имяфайладляпоиска: .
Т.е. это не знак /s, это конструкция s|||. В sed не обязательно использовать символ "/" в качестве разделителя s
Mingun
Потому что в этой статье материал подан так, что «а вот это заклинание делает вот такую магию», потому ничего и не понятно. Лучше почитайте краткий учебник по sed и всё сразу встанет на свои места. В вашем примере общий вид команды sed такой:
где
<адресное выражение>
—/некоесловодляпоиска/
, то есть регулярное выражение (идентифицируется двумя косыми чертами//
), с которым должна совпасть строка, чтобы следующая за ним команда её обработала, а<команда замены>
—s|<что заменить>|<на что заменить>|<флаг>
(разделителями команды заменыs
могут выступать не только косые черты, а любой другой символ, в данном случае символ вертикальной черты|
). В<что заменить>
указана каретка^
, то есть, начало строки (по сути — некая позиция), а в<на что заменить>
— текст, который по итогу будет в начало строки добавлен. Последний символp
— это флаг командыs
, указывающий ей распечатать результат замены.Joker2147
Небольшое уточнение: p - это не флаг команды s, а самостоятельная команда "print".
Mingun
Нет, в данном случае это именно флаг. Фрагмент из справочной страницы sed'а:
Отдельную команду
p
тоже, конечно, можно использовать, только тогда её, во-первых, надо будет отделить символом точка с запятой;
от командыs
(в случае однострочной записи, как оно и бывает при вызове из терминала, либо расположить их на разных строках, если пишем отдельный скрипт для sed'а), а во-вторых, заключить обе команды в блок — фигурные скобки{}
— потому что иначе адресное выражение будет относиться только к первой команде: