- «розумне» додавання подвійного інтервалу між рядками
- вилучення пустих рядків
- додавання пустих рядків над і під вибраним текстом
- вилучення парних або непарних рядків
2. нумерація рядків
2.1. проста нумерація рядків
задача: пронумерувати кожен рядок вхідного файлу.sed = | sed 'N;s/\n/\t/'
ага, починаються значно складніші приклади. тут маємо насправді дві різних команди. перший sed застосовує команду =, котра просто виводить у вихідний потік номер поточного рядка, а тоді — новим рядком — виводить текст з робочого буфера. побачити, як це працює, можна на простому прикладі:cat test.txt | sed =
результат буде такий:1
Бринь бандура, та й замовкне…
2
Чом же не заграє?
3
Стоїть старець під віконцем, —
4
Чом же не співає?
…і т.д. не зовсім те, що треба — хотілося би об’єднати номер і подальший текст в одному рядку. для цього потрібен другий sed: він завантажує перший рядок виводу («1») в робочий буфер, команда N (від next — наступний) додає до робочого буфера (pattern space) символ переносу рядка (\n), а тоді завантажує і приєднує наступний рядок з вхідного потоку («Бринь бандура, та й замовкне…») — це вже близько, але треба позбутися того зайвого \n посередині… тут працює команда s///, котра шукає в робочому буфері фрагмент тексту за шаблоном і заміняє на вказаний фрагмент — в нашому випадку шукає символ \n (новий рядок) і заміняє на \t (табуляція).приклад:
cat test.txt | sed = | sed 'N;s/\n/\t/'
результат: вивід тексту з нумерацією рядків і табульованим відступом зліва.2.2. нумерація рядків з вирівнюванням номеру вправо
задача: пронумерувати кожен рядок вхідного тексту, вирівнявши номери по правій стороні.sed = | sed 'N; s/^/ /; s/ *\(.\{6,\}\)\n/\1 /'
важливо! sed дуже чутливий до синтаксису рядка з параметрами… кожен символ важливий. буквально наявність чи відсутність пробілу перед зірочкою * в команді може означати помилку в роботі команди. враховуючи загальну нечитабельність синтаксису команд sed і регулярних виразів — тут є над чим задуматися новачкові.перша частина зрозуміла (див. п. 2.1) — це вставка нумерації перед кожним текстовим рядком. далі: команда N з’єднує два рядки (номер і наступний текстови й рядок) в один, з переносом рядка (
\n
) десь посередині. команда s/^/<тут_5_пробілів>/
— це вже знайома команда пошуку і заміни (див. п. 2.1), котра вставляє необхідну кількість пробілів на початку кожного рядка (регулярний вираз ^
означає якраз початок рядка).отже, якщо взяти для прикладу перший рядок тестового файлу, на цьому етапі в робочому буфері sed матиме таке (пробіли заміняю мінусами - для наглядности):
-----1\nБринь бандура, та й замовкне…
наступна команда s
містить складний регулярний вираз, якщо прибрати зворотні похилі риски, що позначають екранування спеціальних символів, маємо такий шаблон: -*(.{6,})\n
(пробіл замінено на мінус). він означає, що треба знайти у робочому буфері нуль або більше символів -
, за котрим йтиме фрагмент з 6 будь-яких символів (.{6,}
), за котрим у свою чергу йтиме символ нового рядка \n
.важливо! дужки змушують sed запам’ятати в першій тимчасовій змінній все, що відповідає частині регулярного виразу в дужках — тобто в моєму прикладі шість символів зі знайденого фрагменту, без зайвих
-
і без \n
.отже, на прикладі першого рядка з тестового файлу, буде знайдено фрагмент:
-----1\n
а в першій тимчасовій змінній опиниться такий фрагмент:-----1
остання частина цієї команди (тобто /\1 /
) заміняє знайдений фрагмент вмістом першої тимчасової змінної (\1
) плюс два пробіли (для відступу до тексту). очевидно, що «зайвого» символу \n
ми позбулися — а якби номер складався не з однієї цифри 1, а з двох, трьох чи п’яти (наприклад -----123
), то і «зайві» мінуси зліва також було би видалено і залишено лише шість символів з номером включно (---123
)!поекспериментувавши з наглядними мінусами замість пробілів у команді, їх треба знову замінити на пробіли — і готово, задачу виконано.
приклад:
cat test.txt | sed = | sed 'N; s/^/ /; s/ *\(.\{6,\}\)\n/\1 /'
результат: 1 Бринь бандура, та й замовкне…
2 Чом же не заграє?
3 Стоїть старець під віконцем, —
4 Чом же не співає?
2.3. нумерація лише непустих рядків
задача: пронумерувати лише непусті рядки в тексті.sed '/./=' | sed '/./N; s/\n/ /'
перший sed відбирає лише ті рядки, в яких є бодай один символ (/./
) — і додає перед ними поточний номер рядка (див. п. 2.1), пусті рядки виводяться без змін. другий sed знову вибирає непустий рядок, з номером (/./
), поєднує його з наступним текстовим (N
), пропускаючи пусті рядки без змін; наступна команда заміни s
позбувається символа \n
всередині кожного рядка, заміняючи його на пару пробілів для відступу.приклад:
cat test.txt | sed '/./=' | sed '/./N; s/\n/ /'
результат:1 Бринь бандура, та й замовкне…
2 Чом же не заграє?
3 Стоїть старець під віконцем, —
4 Чом же не співає?
6 Ой ходив би я по селах
7 Од хати до хати,
8 Ой співав би на ввесь голос, —
9 Нікому співати!
важливо! очевидно, що результат дивний — пустий рядок не має номера, але нумерація таки враховує його як п’ятий. це особливості роботи команди =
, вона ж бо виводить поточний номер зчитаного рядка, незалежно від того, пустий він чи ні! щоби реалізувати правильну нумерацію, котра справді ігноруватиме пусті рядки — треба подумати. пізніше візьмуся до цього.2.4. підрахувати кількість рядків у тексті
задача: підрахувати кількість рядків у тексті й вивести в термінал.sed -n '$='
опція -n
змушує sed не виводити нічого у вихідний потік, якщо вивід не вимагається явно командою (такою, як p
чи деякі інші). команда =
виводила б номер кожного зчитаного рядка… якби не модифікатор $
, котрий застосовує команду лише до останнього рядка у вхідному потоці. тобто у вивід попаде лише номер останнього рядка — і більше нічого.приклад:
cat test.txt | sed -n '$='
для тестового файлу результат буде такий:9
команда нарахувала 9 рядків — враховано і пустий рядок у файлі, як і в попередньому прикладі (див. п. 2_3).наразі все з нумерацією. далі ще буде.