Потоковий редактор sed

Тепер розглянемо програму sed Це буде не дуже складно зробити, так як вона є прямим нащадком редактора ed, знайомство з ним облягає задачу

Основна ідея sed дуже проста:

$ sed список команд ed імена5файлов

читає построчно вхідний файл виконує по черзі команди зі списку над кожним рядком і виводить результат на стандартне уст-

ройство виводу Так, можна замінити всі входження UNIX на UNIX (TM) у групі файлів командою

$ sed s / UNIX / UNIX (TM) / g імена5файлов ..> output

Не помиліться в тому, що тут відбувається: sed НЕ змінює вмісту вхідних файлів, а використовує стандартний висновок, залишаючи вихідні файли недоторканими Ви вже досить добре знаєте оболонку, щоб розуміти, що не слід писати:

$  sed  ’…’  file  &gtfile

Для заміни вмісту файлу слід використовувати або тимчасовий файл, або іншу програму (Пізніше ми обговоримо програму, що реалізовує ідею перезапису існуючого файлу см overwrite в розділі 5)

Висновок кожного рядка в sed виконується автоматично, тому немає необхідності додавати p після команди підстановки, – якщо це зробити, то кожна змінена рядок буде надрукована двічі У той же час лапки майже завжди необхідні, так як багато метасимволи sed мають власне значення в оболонці Розглянемо, наприклад, команду du-a, друкувальну список файлів Зазвичай du виводить розмір і імя файлу:

$ du –a  ch4*

18                 ch41

13&nbsp&nbsp ch42

14&nbsp&nbsp ch43

17                 ch44

2                   ch49

$

Видалення стовпця з розмірами можна здійснити за допомогою sed, але команда редагування вимагає наявності лапок, щоб не допустити інтерпретації оболонкою символу * і знака табуляції:

$ du  –a  ch4*  |  sed  ’s/*6//’

ch41 ch42 ch43 ch44 ch49

$

У процесі підстановки видаляються всі символи ( *) До останнього спра ва знака табуляції включно (в шаблоні він показаний знаком 6) 1

1 У сучасних реалізаціях оболонки користувача, наприклад в bash, для приміщення в командний рядок «справжнього» символу табуляції обхідно безпосередньо перед ним ввести Ctrl5V Редактор командного рядка оболонки csh зазвичай використовує за замовчуванням для введення символів, що не вимагають інтерпретації, цей же керуючий символ – Прямуючи науч ред

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

$ who

lr             tty1               Sep  29  07:14 ron           tty3               Sep  29  10:31 you           tty4               Sep  29  08:36 td             tty5               Sep  29  08:47

$  who  |  sed  ’s/  *  /  /’ lr  07:14

ron  10:31

you 08:36 td  08:47

$

Команда s виконує заміну пробілу і всього, що з ним слід, включаючи наступний пробіл, єдиним пропуском Тут теж необхідні лапки

Практично така ж команда sed застосовується в програмі getname, що повертає імя поточного користувача:

$ cat  getname

who  am  i  |  sed  ’s/  *//’

$ getname

you

$

Ще одна команда sed застосовується настільки часто, що ми вбудували її в оболонку під імям ind Команда ind додає у вхідний файл відступ зліва на один крок табуляції, це дозволяє краще розташувати текст при друку на принтері

Реалізація ind надзвичайно проста – в початок кожного рядка додається знак табуляції:

sed  s/^/6/’  $*                 ind,  версія 1

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

sed  //s/^/6/’  $*         ind,  версія 2

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

Є й інший спосіб реалізації команди ind Додавши в початок команди знак оклику, Можна обробляти тільки ті рядки, які НЕ відповідають шаблону:

sed  /^$/s/^/6/’  $*         ind,  версія 3

Шаблон / ^ $ / визначає порожні рядки (кінець рядка слід відразу за її початком), таким чином / ^ $ / означає «не виконувати команду на порожніх рядках»

Як говорилося вище, sed автоматично виводить рядки незалежно від того, були вони оброблені чи ні (якщо тільки вони не були видалені ни) Крім того, можна використовувати більшість команд редактора ed Тому не представляє праці написати програму, яка печа тане перші три (наприклад) прочитання рядка і завершує роботу:

sed  3q

Хоча 3q і не є командою ed, вона має сенс у sed: копіювати рядки три рази, потім вийти

Може знадобитися додаткова обробка даних, наприклад вирівнювання Для цієї мети можна було б перенаправити висновок sed на вхід ind, але, оскільки sed здатний виконувати декілька команд одночасно, всю роботу можна виконати одним викликом sed:

sed  s/^/6/ 3q’

Зверніть увагу на те, як розташовані лапки і символ нового рядка, кожна команда повинна знаходитися на окремому рядку, при цьому sed ігнорує початкові пробіли і знаки табуляції

Може виникнути бажання написати програму – назвемо її head – для друку перших кількох рядків файлів Але набрати на клавіатурі sed 3q (або 10q) настільки просто, що, швидше за все, таку програму писати немає сенсу Тим не менш, ми у своїй системі застосовуємо ind, так як відповідна йому команда sed дещо складніше (В процесі написання ми замінили 30-рядкову програму на С однорядковою командою версії 2, розглянутої вище) Ні точного критерію доцільності заміни складної командного рядка однією командою ось найкраще з правил, які нам вдалося виробити, – помістіть нову команду в свій каталог / bin і подивіться, як часто ви будете її використовувати

Можна також помістити команди sed у файл і викликати їх звідти рядком

$ sed  –f    cmdfile ..

Вибирати рядка можна не тільки по їх номерах, зокрема команда

$ sed / шаблон / q

надрукує рядка від початку файлу до першого рядка, відповідної шаблоном, Включаючи і цей рядок, а команда

$ sed / шаблон / d

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

Автоматичний висновок результатів, цілком придатний в більшості випадків, іноді буває небажаний Він може бути вимкнений пара метром-n в цьому випадку виводяться лише рядки, явно відправлені на друк командою p Наприклад,

$ sed-n / шаблон / p

робить те ж саме, що і grep А оскільки умова збігу може бути інвертований, то команда

$ sed-n / шаблон / p

еквівалентна grep-v (Так само як і sed /шаблон/d’)

Навіщо використовувати обидві команди – sed і grep Зрештою, grep – всього лише простий окремий випадок sed Частково це пояснюється історичними причинами – команда grep зявилася набагато раніше, ніж sed Але grep живе і процвітає завдяки своїй лаконічності: з її допомогою простіше виконати ту роботу, яку обидві команди виконують однаково (Команда grep має функції, відсутні в sed, наприклад, визначаються параметром-b) Хоча буває, що програми вмирають Була колись програма gres, яка виконувала прості підстановки, зникла майже відразу після появи sed

Символи нового рядка можуть бути додані за допомогою sed аналогічно тому, як це робилося в ed:

$ sed  ’s/$/\

&gt /’

Ця команда додає до всіх рядків символ нового рядка, збільшуючи вдвічі їх кількість

$ sed  ’s/[ 6][  6]*/\

&gt /g’

А ця замінює послідовності прогалин і символів табуляції одним символом роздільника рядків, поміщаючи кожне слово на окремому рядку (Регулярний вираз [6] відповідає прогалині або знаку табуляції, а [6] * нулю або більше тих же символів, так що вираз в цілому визначає один або кілька пробілів і / або знаків табуляції)

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

$ sed-n 20, 30p Вивести рядки з 20 по 30

$ sed  1,10 d Видалити рядки з 1 по 10 (= tail +11)

$ sed  1, / ^ $ / d Видалити до першого порожнього рядка включно

$ sed  –n / ^ $ /, / ^ End / p Вивести всі групи рядків, що починаються

з порожньою рядки і закінчуються рядком, що починається словом end

$ sed  $ D Видалити останній рядок

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

Відсутність відносної нумерації рядків є фундаментальним обмеженням програми sed, відсутнім в редакторі ed Зокрема, знаки + і – не обробляються у виразах для номерів рядків, тому неможливо повернутися назад у вхідному потоці:

$ sed  $-1d Неприпустимо: посилання назад заборонені

Unrecognized  command:  $–1d

$

Після того як чергова рядок прочитана, попередня зникає назавжди: немає способу звернутися до рядка, «сусідній» з поточною, як вимагає ця команда (Якщо бути чесними до кінця, потрібно сказати, що така можливість є, але вона вимагає поглибленого вивчення команди hold) Відносна адресація вперед також недоступна:

$ sed  / Thing / +1 d Неприпустимо: посилання вперед заборонені

Зате є можливість виводити дані в кілька файлів Наприклад,

$ sed  –n /pat/w  file1

&gt                        / Pat / W file2 імена5файлов

$

виводить рядки, відповідні шаблоном pat в file1, а решта – в

file2 Або, повертаючись до першого прикладу,

$ sed  s / UNIX / UNIX (TM) / gw uout імена5файлов ..> output

Така команда, як і раніше, виведе всі рядки в файл output, але, крім цього, створить файл uout для змінених рядків

Іноді потрібно передати імена файлів, задані параметрами в оболонці, в тіло команди sed Прикладом такої взаємодії є програма newer, яка виводить імена файлів, створених пізніше зазначеного файлу

$ cat  newer

# Newer f: вивести імена файлів, створених після f ls-t | sed/^$/q

$

Лапки запобігають інтерпретацію спеціальних символів оболонкою, а $ 1 замінюється імям файлу Інший спосіб передачі аргу мента:

&quot/^\$/q&quot

Тут замість $ 1 буде підставлено значення, а \ $ перетвориться в $

Аналогічно виглядає програма older, яка виводить імена фай лов, створених раніше зазначеного:

$ cat  older

# Older f: вивести імена файлів, створених раніше f ls-tr | sed/^$/q

$

Єдина відмінність полягає в параметрі-r команди ls, распо лага список у зворотному порядку

Незважаючи на те що програма sed має набагато більше можливостей, ніж тут було показано (включаючи перевірку умов, цикли і переходи, запамятовування попередніх рядків), і, зрозуміло, виконує більшість команд редактора ed, який описаний у додатку 1, найбільш часто вона застосовується саме так, як тут було описано – з однією-двома командами редагування, без використання довжин них і складних виразів Основні можливості sed описані в табл 42, хоча там відсутні багаторядкові функції

Таблиця 42 Команди програми sed

Команда Дія

a \ дописувати у вихідний файл рядки, що знаком \ b label               перехід до мітці label

c \ замінити рядки зазначеним текстом, в якому рядки закінчуються знаком \

d видалити рядок і прочитати наступну з вхідного потоку

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

l вивести рядок з відображенням недрукованих символів

p вивести рядок

q вийти

r file                  читати файл file, Копіювати вміст у вихідний потік

s /old/new/f  замінити фрагмент old фрагментом new Приf= G замінити всі, при f= P друкувати, при f=w file писати в file

Таблиця 42 (продовження)

Команда

Дія

t label

w file

y /str1/str2/

=

cmd

: label

{

перевірка: перейти до мітці label, Якщо в поточному рядку виконана підстановка

вивести рядок в файл file

замінити всі символи рядка str1 відповідними символами рядка str2 (Діапазони недопустимі)

вивести номер поточного рядка

виконати команду cmd, Тільки якщо рядок не обрана встановити мітку label для команд b і t

згрупувати команди до наступного символу}

Програма sed зручна тим, що може обробляти файли довільної довжини, працює швидко і має багато спільного з редактором ed, в тому числі регулярні вирази і порядкову обробку З іншого боку, до її недоліків можна віднести обмежену можливість запамятовування (важко переносити текст з одного рядка в іншу), обробку даних тільки за один прохід, неможливість переміщення назад, відсутність посилань вперед (/ .. / +1) і відсутність коштів для обчислень – це всього лише текстовий редактор

Вправа 45 Змініть програми older і newer так, щоб вони не виводили імя переданого їм файлу Змініть порядок виведення на зворотний ~

Вправа 46Використовуйте sed, щоб підвищити надійність програми bundle Підказка: при використанні вбудованих документів маркер кінця розпізнається тільки при точній відповідності рядку ~

Джерело: Керниган Б, Пайк Р, UNIX Програмне оточення – Пер з англ – СПб: Символ-Плюс, 2003 – 416 с, Мул

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*