До кінця цього розділу ви дізнаєтесь про наступне:

  • що таке sed
  • інтерактивне використання sed
  • формальні вирази та редагування потоків
  • вживання команд sed в сценаріях

Підказка: Це всього лише вступ

Всі пояснення є далекими від досконалості та звісно не передбачаються як визначальний посібник для користувача sed. Цей розділ включено з метою показати дещо цікавіші теми в наступних розділах, а ще тому, що кожен досвідчений користувач повинен знати про можливості, що можуть бути реалізовані з допомогою цього редактора.

Для детальнішої інформації зверніться до сторінок довідки sed – info та man.

Вступ

Що таке sed?

Sed (англ stream editor — потоковий редактор) використовується для перетворення тексту, зчитаного з звичайного чи абстрактного файлу (pipe). Результат роботи відправляється на стандартний вивід. Синтаксис команди sed не передбачає вказування вихідного файлу, а результат зберігається у файлах з допомогою перенаправлення. Редактор не модифікує вхідний файл.

Що відрізняє sed від таких редакторів як ?vi чи ed, так це можливість відфільтровувати текст, що він отримує по конвеєру. Вам не потрібно взаємодіяти з редактором, коли він запущений, тому sed іноді називають пакетним редактором. Ця властивість дозволяє використовувати команди редагування в сценаріях, значно полегшуючи одноманітні задачі по редагуванню текстів. Якщо вам трапляється замінювати текст у великій кількості файлів, тоді sed — чудовий інструмент для полегшення роботи.

Команди sed

sed дозволяє виконувати підстановки та видалення фрагментів тексту за допомогою регулярних виразів, як наприклад у команді grep. Команди редагування ідентичні до тих, що використовуються у редакторі vi: Окремо від команд редагування ви можете передавати опції у sed; їх огляд подається нижче. Сторінки довідки info містять значно більшу кількість інформації про sed; ми ж навели лише найбільш вживані команди та опції.

a\ : вставити текст під поточним рядком

c\ : замінити текст у поточному рядку новим

d\ : видалити текст

i\ : вставити текст над поточним рядком

p : видрукувати текст

r : зчитати файл

s : шукати та замінити текст

w : записати у файл

-e СЦЕНАРІЙ : Додати команди з сценарію до набору команд, що запускатимуться під час обробки вводу.

-n : Спрощений режим

-V : Надрукувати інформацію про версію та завершити роботу

Інтерактивне редагування

Друк рядків, що містять вираз

Звісно, це ж саме ви можете робити й за допомогою команди grep, але ви не зможете зробити нею пошук та заміну; цей приклад лише допоможе вам освоїтись. Ось наш тестовий файл:

sandy ~> cat -n example
    1  Це перший рядок у прикладах.
    2  Це текст з помлками.
    3  Багато помлк.
    4  Так багато помлк, що через ці помлк я зараз захворію.
    5  Цей рядок не містить помилок.
    6  Це останній рядок.

sandy ~>

Ми хочемо, щоб sed знайшов нам всі рядки з певним виразом, ну, наприклад, “помлк”. Для цього використовуватимемо опцію p:

sandy ~> sed  '/помлк/p' example
Це перший рядок у прикладах.
Це текст з помлками.
Це текст з помлками.
Багато помлок.
Багато помлок.
Так багато помлок, що через ці помлки я зараз захворію.
Так багато помлок, що через ці помлки я зараз захворію.
Цей рядок не містить помилок.
Це останній рядок.

sandy ~>

Як бачите, sed роздрукував цілий файл, а рядки, що містять шуканий вираз – аж двічі. Це не зовсім те, що ми хотіли. Для того, щоб друкувати тільки ті рядки, що відповідають зразку, використайте опцію -n:

sandy ~> sed -n '/erors/p' example
Це текст з помлками.
Багато помлок.
Так багато помлок, що через ці помлки я зараз захворію.

sandy ~>

Видалення з виводу рядків, що містять заданий вираз

Ми будемо використовувати той самий тестовий файл. Тепер ми хочемо побачити рядки, що НЕ містять стрічки пошуку:

sandy ~> sed '/помлк/d' example
Це перший рядок у прикладах.
Цей рядок не містить помилок.
Це останній рядок.

sandy ~>

Рядки, що розпочинаються з заданого шаблону та завершуються іншим заданим шаблоном шукаються приблизно ось так:

sandy ~> sed -n '/^Цей.*помилок.$/p' example
Цей рядок не містить помилок.

sandy ~>

Діапазони рядків

Тепер нам потрібно вилучити рядки, що містять помилки. В нашому випадку це є рядки з другого по четвертий. Задамо цей діапазон за допомогою команди d:

sandy ~> sed '2,4d' example
Це перший рядок у прикладах.
Цей рядок не містить помилок.
Це останній рядок.

sandy ~>

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

sandy ~> sed '3,$d' example
Це перший рядок у прикладах.
Це текст з помлками.

sandy ~>

Ця команда роздруковує лише перші два рядки з прикладу. Наступна команда роздруковує файл від першого рядка, що містить вираз “текст” і аж до рядка, в якому зустрічається вираз “рядок”:

sandy ~> sed -n '/a текст/,/рядок/p' example
Це текст з помлками.
Багато помлк.
Так багато помлк, що через ці помлк я зараз захворію.
Цей рядок не містить помилок.

sandy ~>

Пошук та заміна за допомогою sed

Тепер ми спробуємо замінити рядки з помилками (ланцюжок “помл”) замість того щоб видруковувати їх

sandy ~> sed 's/помл/помил/' example
Це перший рядок у прикладах.
Це текст з помилками.
Багато помилок.
Так багато помилок, що через ці помлки я зараз захворію.
Цей рядок не містить помилок.
Це останній рядок.

sandy ~>

Як бачите, це також не зовсім те, на що ми розраховували: в четвертому рядку замінено лише перший екземпляр ланцюжка “помл”. Вживайте команду g щоб вказати sed, щоб він перевіряв рядок до кінця, а не припиняв його аналіз після першого здобутку:

sandy ~> sed 's/помл/помил/g' example
Це перший рядок у прикладах.
Це текст з помилками.
Багато помилок.
Так багато помилок, що через ці помилки я зараз захворію.
Цей рядок не містить помилок.
Це останній рядок.

sandy ~>

Вставка довільного ланцюжка символів на початку кожного рядка, наприклад для цитування:

sandy ~> sed 's/^/> /' example
> Це перший рядок у прикладах.
> Це текст з помилками.
> Багато помилок.
> Так багато помилок, що через ці помлки я зараз захворію.
> Цей рядок не містить помилок.
> Це останній рядок.

sandy ~>

А тепер вставимо щось в кінець рядка:

sandy ~> sed 's/$/EOL/' example
Це перший рядок у прикладах.EOL
Це текст з помилками.EOL
Багато помилок.EOL
Так багато помилок, що через ці помлки я зараз захворію.EOL
Цей рядок не містить помилок.EOL
Це останній рядок.EOL

sandy ~>

Декілька команд пошуку й заміни можна розділити індивідуальними опціями -e:

sandy ~> sed -e 's/помл/помил/g' -e 's/останній/кінцевий/g' example
Це перший рядок у прикладах.
Це текст з помилками.
Багато помилок.
Так багато помилок, що через ці помлки я зараз захворію.
Цей рядок не містить помилок.
Це кінцевий рядок.

sandy ~>

Запам'ятайте, що за замовчуванням sed виводить свої результати на стандартний вивід, швидше за все – на вікно вашого терміналу. Якщо ви хочете зберегти результат у файлі – перенаправте його:

sed опції 'якийсь/вираз' файл_для_обробки > файл_для_зберереження_результату

Примітка: Додаткові приклади

Чимало прикладів вживання sed ви зможете знайти в стартових сценаріях вашої машини, які як правило знаходяться в каталогах /etc/init.d або /etc/rc/init.d. Перейдіть в цей каталог та запустіть команду:

grep sed *

Неінтерактивне редагування

Зчитування команд sed з файлу

Декілька команд sed можуть бути записані у файл та виконані за допомогою опції -f. Коли будете створювати такий файл, переконайтесь, що:

  • в кінці рядків немає символів <tab>, <пробіл>
  • не використано лапок
  • коли вводите текст для додавання чи заміни, всі рядки за винятком останнього завершуються символом зворотної косої

Запис файлів виводу

Запис файлів виводу реалізовується за допомогою символу перенаправлення “>”. Нижченаведений сценарій використовується для формування дуже простих файлів HTML з звичайних текстових файлів:

sandy ~> cat script.sed
1i\
<html>\
<head><title>html, згенерований sed-ом</title></head>\
<body bgcolor="#ffffff">\
<pre>
$a\
</pre>\
</body>\
</html>

sandy ~> cat txt2html.sh
#!/bin/bash

# Це простий сценарій для перетворення текстів у HTML.
# Спершу ми видалим всі символи нового рядка, що зустручаються лише
# один раз, а потім замінимо ті, що залишились.

echo "перетворюється $1..."

SCRIPT="/home/sandy/scripts/script.sed"
NAME="$1"
TEMPFILE="/var/tmp/sed.$PID.tmp"
sed "s/\n/^M/" $1 | sed -f $SCRIPT | sed "s/^M/\n/" > $TEMPFILE
mv $TEMPFILE $NAME

echo "готово."

sandy ~>

$1 містить перший аргумент, переданий команді, в даному випадку файл для перетворення:

sandy ~> cat test
line1
line2
line3

Більше про позиційні параметри ви можете дізнатись із розділу 7.

sandy ~> txt2html.sh test
перетворюється test...
готово.

sandy ~> cat test
<html>
<head><title>html, згенерований sed-ом</title></head>
<body bgcolor="#ffffff">
<pre>
line1
line2
line3
</pre>
</body>
</html>

sandy ~>

Звісно, це ще не все; даний приклад просто демонструє можливості sed. Перегляньте параграф 6.3 для детальнішого вирішення цієї проблеми за допомогою awk та конструкцій BEGIN та END.

Підказка: Легкий sed

Розвинені редактори, що підтримують підсвітку синтаксису, можуть розпізнавати синтаксис sed. Це може бути чудовою допомогою якщо ви частенько забуваєте ставити зворотні косі риски абощо.

Підсумок

Потоковий редактор sed є потужним інструментом, який може обробляти потоки даних: він може брати вхідні рядки із абстрактних файлів (pipe), що дозволяє використовувати його для неінтерактивної обробки. Редактор використовує команди у стилі vi та розуміє регулярні вирази.

Програма sed може зчитувати команди з командного рядка чи з файлу. Вона часто використовується для реалізацій операцій пошуку та заміни.

Вправи

Ці вправи покажуть, як ще можна використовувати sed.

  1. Роздрукуйте список файлів, що знаходяться у вашому каталозі scripts та закінчуються на “sh”. Зауважте, що, можливо, вам доведеться розіменувати ls. Збережіть результат у тимчасовому файлі.
  2. Зробіть список файлів /usr/bin, що мають літеру “a” в другій позиції. Збережіть результат у тимчасовому файлі.
  3. Витріть по 3 рядки з кожного з тимчасових файлів.
  4. Виведіть на стандартний вивід ті рядки, що містять шаблон “an”.
  5. Створіть файл з командами sed, які автоматизовують попередні дві задачі. Допишіть в цей команду, яка додає рядок на кшталт “Це має щось робити з сторінками довідки” перед кожним рядком, у котрому зустрічається слово man (довідник). Перевірте результат.
  6. Довгий список каталогів кореневого каталогу використовується в якості вводу. Створіть файл з командами sed, що відділяє символічні лінки (symbolic links) та звичайні файли. Якщо файл є символічним лінком, то попередьте про це рядком наподобі “Це – символічний лінк”, якщо ж файл є звичайним файлом, додайте в той самий рядок коментарій наподобі “-- є звичайним файлом”
  7. Напишіть сценарій, що показує рядки з порожніми завершальними символами у файлі. Цей сценарій повинен використовувати інший сценарій sed та виводити користувачеві зручну для сприймання інформацію.