Команди попередньо обробки

У KDiff3 підтримуються два параметри попередньої обробки.

Команда препроцесора:

Під час читання будь-якого файла його буде оброблено вказаною зовнішньою програмою. Замість вмісту початкового файла ви побачите дані, виведене відповідною програмою. Ви можете написати ваш власний інструмент попередньої обробки (препроцесор), який виконуватиме потрібні вам дії. Препроцесор може вирізати непотрібні частини файлів або автоматично виправити відступи тощо.

Команда відповідності рядків препроцесора:

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

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

Приклад. Простий тест: розглянемо файл a.txt (6 рядків):

aa
      ba
      ca
      da
      ea
      fa

і файл b.txt (3 рядки):

cg
      dg
      eg

Якщо не використовувати препроцесора, у відповідність буде "#~ "поставлено такі рядки:

aa - cg
      ba - dg
      ca - eg
      da
      ea
      fa

Навряд чи ми бажали саме цього, оскільки насправді важливу інформацію містить перша літера рядка. Щоб допомогти алгоритмові пошуку відповідників уникнути порівняння за другою літерою, ми можемо скористатися командою-препроцесором, яка замінить «g» на «a»:

sed 's/g/a/'

У результаті виконання цієї команди порівняння матимемо:

aa
      ba
      ca - cg
      da - dg
      ea - eg
      fa

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

Основи sed

Цей розділ є лише вступом, у якому обговорено найпростіші можливості команди sed. Докладніші відомості можна знайти на сторінці info:/sed або http://www.gnu.org/software/sed/manual/html_mono/sed.html. Зібрану версію цієї програми для Windows® можна знайти за адресою http://unxutils.sourceforge.net. Зауважте, що у наведених нижче прикладах припускається, що файл програми sed зберігається у одній з тек, які вказано у змінній середовища PATH. Якщо це не так, вам доведеться вказувати повний абсолютний шлях до файла програми.

У цьому контексті використовується лише команда заміни sed:

sed 's/ФОРМАЛЬНИЙ_ВИРАЗ/ЗАМІННИК/ПРАПОРЦІ'

Перш ніж користуватися новою командою у KDiff3, вам слід спочатку випробувати її у консолі. Для такої перевірки вам знадобиться команда echo. Приклад:

echo abrakadabra | sed 's/a/o/'
   -> obrakadabra

У цьому прикладі ми продемонстрували дуже просту команду sed, яка заміняє перше знайдене «a» на «o». Якщо ви бажаєте замінити всі «a», вам слід скористатися прапорцем «g»:

echo abrakadabra | sed 's/a/o/g'
   -> obrokodobro

Символ «|» використовується для створення конвеєрів: дані, виведені попередньою командою, передаються як вхідні дані наступній команді. Якщо ви бажаєте виконати перевірку на великому файлі, вам слід скористатися командою cat у UNIX®-подібних системах або командою type у Windows®-подібних системах. sed виконає заміну у всіх рядках.

cat назва файла | sed параметри

Приклади використання sed у KDiff3

Ігнорування коментарів інших типів

Поточна версія KDiff3 розуміє лише коментарі у стилі C/C++. За допомогою команди препроцесора пошуку відповідників ви можете наказати програмі ігнорувати інші типи коментарів перетворенням цих коментарів на коментарі C/C++.

Приклад: щоб наказати програмі ігнорувати коментарі, що починаються з «#», вам слід перетворити цей символ на «//». Зауважте, що вам також слід позначити пункт Ігнорувати коментарі C/C++, щоб отримати бажаний результат. Відповідна команда препроцесора пошуку відповідників буде такою:

sed 's/#/\/\//'

Оскільки у sed символ «/» має особливе призначення, у рядку-заміннику перед кожним символом «/» слід додавати символ «\». Цей символ потрібен для додавання або вилучення особливого призначення інших символів. Крім того, символи одинарних лапок (') перед і після команди заміни є важливими лише під час тестування команд командної оболонки, оскільки якщо ви їх не використовуватимете, оболонка виконання команд намагатиметься інтерпретувати деякі символи. Сама програма KDiff3 не виконуватиме інтерпретації, окрім як для послідовностей символів «\"» та «\\».

Пошук відмінностей без врахування регістру

Скористайтеся такою командою препроцесора пошуку відповідників для перетворення усіх символів вхідних даних до верхнього регістру:

sed 's/\(.*\)/\U\1/'

У цій команді ми використали «.*» — формальний вираз, що відповідає будь-якому рядку, а у нашому контексті відповідними вважатимуться всі символи рядка. Послідовність символів «\1» у рядку-заміннику відповідає знайденому тексту у першій парі круглих дужок, «\(» і «\)». Команда «\U» перетворює символи вставленого тексту на символи у верхньому регістрі.

Ігнорування ключових слів системи керування версіями

У CVS та інших системах керування версіями використовується декілька ключових слів, призначених для вставки автоматично створених рядків (див. info:/cvs/Keyword substitution). Всі ці ключові слова буде вказано за схемою: $КЛЮЧОВЕ_СЛОВО створений текст$. Нам буде потрібна команда препроцесора пошуку відповідників, який вилучить лише створений текст:

sed 's/\$\(Revision\|Author\|Log\|Header\|Date\).*\$/\$\1\$/'

Символ «\|» відокремлює можливі варіанти ключових слів. Можливо, вам слід змінити цей список відповідно до ваших потреб. Перед символом «$» обов'язково слід додати символ екранування «\», оскільки у іншому випадку команда вважатиме, що «$» позначає кінець рядка.

Під час експериментів з sed ви краще зрозумієте механізм дії і навіть полюбите формальні вирази. Це буде корисним, оскільки значна кількість інших програм підтримують подібні формальні вирази.

Ігнорування цифр

Насправді ігнорування чисел є вбудованою функцією. Але, як ще один приклад, ми покажемо, як зробити так, щоб під час пошуку відповідників програма ігнорувала числа, за допомогою команди препроцесора порівняння рядків:

sed 's/[0123456789.-]//g'

Препроцесор знайде всі символи, вказані між квадратними дужками, і вилучить їх (замінить на порожнє місце).

Ігнорування певних стовпчиків

Іноді ви маєте справу зі строго форматованим текстом, який містить позиції, які завжди слід ігнорувати, інші ж позиції тексту потрібно проаналізувати. У наступному прикладі буде проігноровано перших п'ять позицій (символів), наступні десять позицій буде збережено, наступні п'ять знову проігноровано, решту рядка буде збережено:

sed 's/.....\(..........\).....\(.*\)/\1\2/'

Кожна крапка «.» замінює собою будь-який одинарний символ. Записи «\1» і «\2» у рядку-заміннику посилаються на знайдений текст у першій і другій парі круглих дужок («\(» і «\)») і є замінниками знайденого тексту без змін.

Комбінування декількох підстановок

Іноді виникає потреба у одночасному виконанні декількох підстановок. У такому випадку ви можете скористатися крапкою з комою («;»), щоб відокремити одну підстановку від інших. Приклад:

echo abrakadabra | sed 's/a/o/g;s/\(.*\)/\U\1/'
   -> OBROKODOBRO

Використання perl замість sed

Замість sed ви можете скористатися, наприклад, perl.

perl -p -e 's/ФОРМАЛЬНИЙ_ВИРАЗ/ЗАМІННИК/ПРАПОРЦІ'

Але у perl ви матимете справу з дещо відмінними конструкціями формальних виразів. Зауважте, що там, де у sed слід використовувати "\(" і "\)", у perl слід використовувати простіший варіант "(" і ")" без попередніх '\'. Приклад:

sed 's/\(.*\)/\U\1/'
   perl -p -e 's/(.*)/\U\1/'

Порядок виконання попередньої обробки

Дані буде пропущено через всі внутрішні та зовнішні препроцесори у такому порядку:

  • Звичайний препроцесор,

  • Препроцесор пошуку рядків,

  • Ігнорування регістру (вважати пробілами) (перетворення на літери верхнього регістру),

  • Визначення коментарів C/C++,

  • Ігнорування чисел (вважати пробілами),

  • Ігнорування пробілів

Після обробки звичайним препроцесором дані не буде змінено: їх буде показано і об'єднано у початковому вигляді. За допомогою інших дій у програмі можна буде змінити лише дані, які було повернуто алгоритмом пошуку відповідних рядків.

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

Попередження

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

З цієї причини під час об'єднання, якщо було використано звичайну команду-препроцесор, KDiff3 повідомить вас про це і запитає про те, бажаєте ви вимкнути наслідки дії цієї команди чи ні. Але програма не попереджатиме вас про використання команди-препроцесора, призначеної для пошуку відповідних рядків. Об'єднання не буде завершено, доки ви не розв'яжете всі конфлікти. Якщо ви знімете позначку з пункту «Показувати пробіли», відмінності, які було вилучено командою-препроцесором пошуку відповідних рядків, також стануть невидимими. Якщо після цього ви не зможете зробити кнопку «Зберегти» активною під час об'єднання (оскільки залишатимуться не розв'язані конфлікти), знову позначте пункт «Показувати пробіли». Якщо ви не бажаєте виконувати розв'язання цих малозначущих конфліктів вручну, ви можете скористатися пунктами «Вибрати A/B/C для всіх нерозв'язаних конфліктів пробілів» з меню «Об'єднання».