Сравнение и объединение файлов diff, diff3, sdiff, cmp, patch : Форматы вывода 'diff'

Вперед Назад Содержание

3. Форматы вывода 'diff'

У 'diff' есть несколько взаимоисключающих опций для задания формата вывода. Следующие разделы посвящены описанию каждого формата, показывая как 'diff' сообщает о различиях на примере двух образцов входных файлов.

3.1 Два образца входных файлов

Далее представлены два образца входных файлов, которые мы будем использовать в нескольких примерах, чтобы показать работу 'diff' и как различные опции ее меняют.

Это файл 'lao':

      The Way that can be told of is not the eternal Way;   
      The name that can be named is not the eternal name.   
      The Nameless is the origin of Heaven and Earth;   
      The Named is the mother of all things.   
      Therefore let there always be non-being,   
        so we may see their subtlety,   
      And let there always be being,   
        so we may see their outcome.   
      The two are the same,   
      But after they are produced,   
        they have different names.   
Это файл `tzu':

      The Nameless is the origin of Heaven and Earth;   
      The named is the mother of all things.   
   
      Therefore let there always be non-being,   
        so we may see their subtlety,   
      And let there always be being,   
        so we may see their outcome.   
      The two are the same,   
      But after they are produced,   
        they have different names.   
      They both may be called deep and profound.   
      Deeper and more profound,   
      The door of all subtleties!   
В этом небольшом примере легко найти различающиеся строки и понять, что для этого примера, первый ханк содержит только первые две строки 'lao', второй ханк содержит четыре строки 'lao', соответствующие второй и третьей строке 'tzu', а последний - три конечные строки 'tzu'.

3.2 Демонстрация различий без контекста

"Нормальный" формат вывода 'diff' показывает каждый ханк различий без какого-либо окружающего контекста. Иногда такой вывод - наиболее ясный способ понять, как изменились строки, не отвлекаясь на соседние неизменившиеся (хотя можно получить такой же результат с контекстным или унифицированным форматом с 0 строками контекста). Тем не менее, этот формат теперь редко используется для пересылки изменений; для этой цели предпочтительнее контекстный (см. "Контекстный формат") и унифицированный (см. "Унифицированный формат") форматы. Нормальный формат принят для совместимости с более ранними версиями 'diff' и стандартом Posix.

Детальное описание нормального формата

Нормальный формат вывода состоит из одного или более ханков различий; каждый ханк показывает на место где файлы различаются. Нормальный формат ханка выглядит так:

      CHANGE-COMMAND   
      < FROM-FILE-LINE   
      < FROM-FILE-LINE...   
      --­   
      > TO-FILE-LINE   
      > TO-FILE-LINE...   
Есть три типа меняющих команд. Каждая состоит из номера строки или разделенной запятыми цепочки номеров в первом файле, одного символа, показывающего какой вид изменения нужно сделать и номера строки или разделенной запятыми цепочки номеров во втором файле. Все номера строк - оригинальные номера строк для каждого файла. Типы меняющих команд следующие:
'LaR'

Прибавляет строки из промежутка R во втором файле после строки L в первом файле. Например, '8a12,15' означает дописать строки 12-15 второго файла после 8 строки первого файла; или, если изменять второй файл в первый, удалить строки 12-15 из второго файла.

'FcT'

Заменяет строки из промежутка F первого файла строками из промежутка T второго файла. Эту команду можно представить как комбинацию добавления и удаления, но более компактную. Например, '5,7c8,10' означает заменить строки 5-7 первого файла на строки 8-10 второго файла; или, если изменять второй в первый, заменить строки 8-10 второго файла на строки 5-7 первого файла.

'RdL'

Удаляет строки из промежутка R первого файла; строка L - это место, где находились бы эти строки во втором файле, если бы их не удалили. Например, '5,7d3' означает удалить строки 5-7 из первого файла; или, если изменять второй файл в первый, добавить строки 5-7 первого файла после 3 строки второго файла.

Пример нормального формата

Далее представлен результат работы команды 'diff lao tzu' (см. "Два образца входных файлов", для полного текста этих файлов). Заметьте, что отображаются только те строки, которые в этих файлах разные.

 1,2d0   
 < The Way that can be told of is not the eternal Way;   
   The name that can be named is not the eternal name.   
 4c2,3    
 < The Named is the mother of all things.    
 --­   
 > The named is the mother of all things.    
 >   
 11a11,13    
 > They both may be called deep and profound.   
 > Deeper and more profound,   
 > The door of all subtleties!   

3.3 Отображение различий в их контексте

Обычно, рассматривая различия между двумя файлами, необходимо также видеть части файлов около отличающихся строк, чтобы легче понять что действительно изменилось. Эти соседние части файлов называются "контекстом".

GNU 'diff' обеспечивает два формата вывода, которые показывают контекст около различающихся строк: "контекстный формат" и "унифицированный формат". Он может оптимальным образом показывать в какой функции или разделе файла были найдены различающиеся строки.

При распространении новых версий файлов среди других людей в форме результатов работы 'diff', следует использовать один из форматов вывода, показывающих контекст изменений, так чтобы они могли применять "изменения" даже если они вносили свои собственные маленькие изменения в файлы. 'patch' может применять "изменения" в этом случае, ища в файлах отличающиеся строки по контексту; если эти строки на самом деле незначительно смещены от указанного в "изменениях" положения, 'patch' может привести номера строк в соответсвие со смещением и все равно применить "изменения" правильно. (См. "Применение несовершенных списков различий", для подробностей использования 'patch' в применении к несовершенным "изменениям").

Контекстный формат

Контекстный формат вывода отображает несколько строк из контекста отличающихся строк. Это стандартный формат для распространения улучшенных исходных текстов.

Чтобы работать в этом формате вывода, используйте опции '-C LINES', '--context[=LINES]', или '-c'. Аргумент LINES, который используется в первых двух опциях, - это количество показываемых строк контекста. Если не указывать аргумент LINES, он принимается равным 3. Для правильной работы 'patch' требуется по крайней мере 2 линии контекста.

Детальное описание контекстного формата

Контекстный формат вывода начинается с двухстрочного заголовка, который выглядит так:

    *** FROM-FILE FROM-FILE-MODIFICATION-TIME   
    --- TO-FILE TO-FILE-MODIFICATION TIME    
Вы можете изменить содержание заголовока с помощью опции '-L LABEL' или '--label=LABEL'; (см. "Альтернативные имена".)

Потом следует один или несколько ханков различий; каждый ханк показывает одно место, где файлы различаются. Контекстный формат ханка выглядит так:

    ***************   
    *** FROM-FILE-LINE-RANGE ****   
      FROM-FILE-LINE   
      FROM-FILE-LINE...   
    --- TO-FILE-LINE-RANGE ---­   
      TO-FILE-LINE    
      TO-FILE-LINE...   
Строки контекста окружающего отличающиеся строки начинаются двумя символами пробела. Строки разные для двух файлов начинаются с одного из следующих символов:
'!'

Строка, являющаяся частью группы из одной или нескольких строк, которые изменились от одного файла к другому. Существует соответствующая группа строк отмеченная '!' в этом же ханке, относящаяся к другому файлу.

'+'

Строка "вставленная" во второй файл, которой нет соответствия в первом файле.

'-'

Cтрока "удаленная" из первого файла, которой нет соответствия во втором файле.

Если все изменения в ханке - вставки, строки "FROM-FILE..." опускаются. Если же все изменения - удаления, опускаются строки "TO-FILE...".

Пример контекстного формата

Далее представлен результат работы команды 'diff -c lao tzu' (см. Два образца входных файлов:: , для полного текста этих файлов). Заметьте, что около каждой отличающейся строки отображается до трех совпадающих; это строки контекста. Также обратите внимание, что первые два ханка идут слитно, так как их контексты перекрываются.

    *** lao     Sat Jan 26 23:30:39 1991   
    --- tzu     Sat Jan 26 23:30:50 1991   
    ****************   
    *** 1,7 ****   
    - The Way that can be told of is not the eternal Way;   
    - The name that can be named is not the eternal name.   
      The Nameless is the origin of Heaven and Earth;      
    ! The Named is the mother of all things.   
      Therefore let there always be non-being,   
        so we may see their subtlety,   
      And let there always be being,   
    --- 1,6 ----    
      The Nameless is the origin of Heaven and Earth;      
    ! The named is the mother of all things.   
    !    
      Therefore let there always be non-being,   
        so we may see their subtlety,   
      And let there always be being,         
    ***************   
    *** 9,11 ****   
    --- 8,13 ----    
      The two are the same,   
      But after they are produced,   
        they have different names.        
    + They both may be called deep and profound.   
    + Deeper and more profound,   
    + The door of all subtleties!   

Пример контекстного формата с меньшим числом строк контекста

Далее представлен результат работы команды 'diff --context=1 lao tzu' (см. "Два образца входных файлов" для полного текста этих файлов). Заметьте, что здесь отображается не больше одной строки контекста.

    *** lao     Sat Jan 26 23:30:39 1991   
    --- tzu     Sat Jan 26 23:30:50 1991   
    ****************   
    *** 1,5 ****   
    - The Way that can be told of is not the eternal Way;   
    - The name that can be named is not the eternal name.   
      The Nameless is the origin of Heaven and Earth;      
    ! The Named is the mother of all things.   
      Therefore let there always be non-being,   
    --- 1,4 ----    
      The Nameless is the origin of Heaven and Earth;      
    ! The named is the mother of all things.   
    !    
      Therefore let there always be non-being,   
    ***************   
    *** 11 ****   
    --- 10,13 ----    
        they have different names.        
    + They both may be called deep and profound.   
    + Deeper and more profound,   
    + The door of all subtleties!   

Унифицированный формат

Унифицированный формат вывода - это вариант контекстного формата, который более компактен, так как не включает избыточные строки контекста. Чтобы задать этот формат вывода, используйте опции '-U LINES', '--unified[=LINES]' или '-u'. Аргумент LINES показывает сколько строк контекста показывать. По умолчанию он равен 3.

На данный момент, только GNU 'diff' может работать с этим форматом и только GNU 'patch' может автоматически применять "изменения" в этом формате. Для правильной работы, 'patch' необходимо по крайней мере 2 строки контекста.

Подробное описание унифицированного формата

Унифицированный формат вывода начинается с двухстрочного заголовка, который выглядит так:

      --- FROM-FILE FROM-FILE-MODIFICATION-TIME   
      +++ TO-FILE TO-FILE-MODIFICATION-TIME   
Вы можете изменить содержание заголовка с помощью опции '-L LABEL' или `--label=LABEL'; (см. "Альтернативные названия".)

Потом следует один или несколько ханков различий; каждый ханк показывает одно место, где файлы различаются. Унифицированный формат ханка выглядит так:

      @@ FROM-FILE-RANGE TO-FILE-RANGE @@   
       LINE-FROM-EITHER-FILE   
       LINE-FROM-EITHER-FILE...   
Строки общие для обоих файлов начинаются с символа пробела. Различающиеся строки имеют один из следующих символов-индикаторов в левой колонке:
'+'

В этом месте строка была прибавлена к первому файлу.

'-'

В этом месте строка была удалена из первого файла.

Пример унифицированного формата

Далее представлен результат работы команды 'diff -u lao tzu' (см. Два образца входных файлов:: , для полного текста этих файлов).

      --- lao   Sat Jan 26 23:30:39 1991   
      +++ tzu   Sat Jan 26 23:30:50 1991   
      @@ -1,7 +1,6 @@   
      -The Way that can be told of is not the eternal Way;   
      -The name that can be named is not the eternal name.   
       The Nameless is the origin of Heaven and Earth;   
      -The Named is the mother of all things.   
      +The named is the mother of all things.   
      +   
       Therefore let there always be non-being,   
         so we may see their subtlety,   
       And let there always be being,   
      @@ -9,3 +8,6 @@   
       The two are the same,   
       But after they are produced,   
         they have different names.   
      +They both may be called deep and profound.   
      +Deeper and more profound,   
      +The door of all subtleties!   

Выяснение, в каких разделах находятся различия

Иногда бывает необходимо знать на какой раздел файлов приходится каждое изменение. Если файлы - это тексты программ, это может касаться изменений функций. Если файлы - документы, это могут быть изменения глав или приложений. GNU 'diff' может сообщать об этом, показывая ближайший заголовок раздела, который предшествует изменяемым строкам. Какие строки считать "заголовками разделов" определяется с помощью регулярного выражения.

Отображение строк соответствующих регулярному выражению

Чтобы показать в каких разделах встретились изменения в файлах не являющихся текстами программ для C или сходного языка, используйте опцию '-F REGEXP' или `--show-function-line=REGEXP'. 'diff' рассматривает строки, которые соответствуют агрументу REGEXP как начала разделов файла. Далее приведены регулярные выражения, заданные для нескольких распространенных языков:

`^[A-Za-z_]'

C, C++, Prolog

`^('

Lisp

`^@\(chapter\|appendix\|unnumbered\|chapheading\)'

Texinfo

Эта опция не задает сама по себе формат вывода; чтобы ее использовать, нужно задать контекстный (см. "Контекстный формат") или унифицированный (см. "Унифицированный формат") формат. В других форматах вывода она не работает.

Опции `-F' и `--show-function-line' находят для каждого ханка различий ближайшую предшествующую ему неизмененную строку, соответствующую данному регулярному выражению. Затем они добавляют эту строку в конец строки звездочек в контекстном формате, или в конце '@@'-строки в унифицированном формате. Если такой строки не найдено, они оставляют ханк неизменненым. Если эта строка состоит более чем из 40 символов, они учитывают только первые 40 символов. Можно указать более одного регулярного выражения для таких строк; 'diff' ищет соответствия для всех строк со всеми регулярными выражениями, начиная с последнего заданного. Это означает, что при желании допустимо использовать опции '-p' и '-F' совместно.

Отображение заголовков функций С

Чтобы отображать в каких функциях обнаружены различия для C или сходного языка, можно использовать опцию `-p' или `--show-c-function'. Эта опция автоматически устанавливает контекстный формат вывода (см. Контекстный формат::.), с заданным по умолчанию количеством строк контекста. Возможно изменение этого числа введением '-C LINES' в командной строке. Можно изменить и формат и число строк контекста с помощью '-U LINES'.

Опции `-p' и `--show-c-function' эквиваленты `-F'^[_a-zA-Z$]'', если указан унифицированный формат, или `-c -F'^[_a-zA-Z$]'' в противном случае (см. Определение заголовков::.). В GNU 'diff' они введены в качестве сокращений.

Отображение альтернативных имен файлов

Если сравниваются два файла, имеющие бессмысленные или неинформативные имена, возможно заставить 'diff' показывать альтернативные имена в заголовке контекстного или унифицированного форматов вывода с помощью опции '-L LABEL' или '--label=LABEL'. Первое применение этой опции заменяет на свой аргумент имя и дату первого файла в заголовке; второе применение заменяет на аргумент имя и дату второго файла. Если попытаться использовать эту опцию еще раз, 'diff' сообщит об ошибке. Опция '-L' не затрагивает имена файлов в заголовке 'pr', когда использована опция '-l' или '--paginate' (см. "Разбивка результатов 'diff' на страницы").

Далее приведены первые две строки результатов работы `diff -C2 -Loriginal -Lmodified lao tzu':

      *** original   
      --- modified   

3.4 Двухстороннее отображений различий

'diff' позволяет двусторонне отображать различия между двумя файлами. Файлы отображаются в двух колонках разделенных колонкой управляющих символов. Колонка управляющих символов состоит из следующих маркеров:

Пробел

Соответствующие строки эквивалентны. Это означает, что либо они одинаковые, или различие игнорировано из-за одной из опций '--ignore' (см. "Пропуски".).

'|'

Соответствующие строки разные, и либо обе приведены полностью, либо обе неполностью.

'<' Строка содержится только в первом файле.

'>'

Строка содержится только во втором файле.

'('

Строка содержится только в первом файле, но различие игнорируется.

')'

Строка содержится только во первом файле, но различие игнорируется.

'\'

Соответствующие строки разные, первая строка приведена неполностью.

'

' /

Соответствующие строки разные, вторая строка приведена неполностью.

Обычно, строка из результатов работы неполна тогда и только тогда, когда строки из которых она состоит неполны (См. "Неполные строки"). Тем не менее, когда результирующая строка представляет две различные строки, одна из них должна быть неполной, в то время как другая наоборот. В этом случае, результирующая строка полна, но в колонку управляющих символов помещается знак '\', если не полна первая строка и '/', если не полна вторая.

Двусторонний формат обычно проще воспринимается, но он имеет свои ограничения. Он генерирует более широкие строки, обрезая непомещающиеся строки. Кроме того, для него более, чем для остальных форматов важна выравненность текста, так что его результаты выглядят особенно плохо при использовании шрифтов разной ширины, нестандартной табуляции, или непечатающихся символов.

Для интерактивного устранения различий при двустороннем формате можно использовать команду 'sdiff'. (См. подробнее "Интерактивное устранение различий").

3.5 Управление двусторонним форматом

Двусторонний формат задается опцией '-y' или '--side-by-side'. Поскольку строки двустороннего формата содержат две исходные строки, они шире, чем обычно. В норме они состоят из 130 символов, так, что могут поместиться в традиционную строку принтера. Их длину можно устанавливать с помощью опции '-W COLUMNS' или '--width=COLUMNS'. Результирующая строка разбивается на две половины равной длины, разделенные маленькой колонкой управляющих символов для отметки различий; правая половина выравнена на границу табуляции. Входные строки, которые не помещаются в половинках выходной строки, обрезаются.

Опция '--left-column' печатает только левую колонку для двух общих строк. Опция '--supress-common-lines' не печатает их вообще.

Пример сравнительного формата

Далее представлен результат работы команды 'diff -y -W 72 lao tzu' (см. Два образца входных файлов:: , для полного текста этих файлов).

      The Way that can be told of is n   <   
      The name that can be named is no   <   
      The Nameless is the origin of He        The Nameless is the origin of He   
      The Named is the mother of all t   |    The named is the mother of all t   
                                         >   
      Therefore let there always be no        Therefore let there always be no   
        so we may see their subtlety,           so we may see their subtlety,   
      And let there always be being,          And let there always be being,   
        so we may see their outcome.            so we may see their outcome.   
      The two are the same,                   The two are the same,   
      But after they are produced,            But after they are produced,   
        they have different names.              they have different names.   
                                         >    They both may be called deep and   
                                         >    Deeper and more profound,   
                                         >    The door of all subtleties!   

3.6 Создание набора команд редактирования

Несколько режимов вывода создают управляющие файлы для редактирования FROM-FILE с целью получения TO-FILE.

Командные файлы для 'ed'

'diff' позволяет составлять командный файл, показывающий текстовому редактору 'ed' как изменить первый файл во второй. Раньше это был единственный формат вывода, позволяющий делать из одного файла другой автоматически; сегодня, благодаря утилите 'patch', он практичеки устарел. Чтобы задать этот формат используйте опцию '-e' или '--ed'.

Как и в нормальном формате (см. "Нормальный формат".), этот формат вывода не показывает контекста; но в отличие от нормального формата, он не включает информацию, необходимую для обращения "изменений" (воссоздания первого файла, при наличии второго и "изменений").

Если файл 'd' содержит результаты работы команды 'diff -e old new', то команда '(cat d && echo w) | ed -old' редактирует файл 'old' для создания копии 'new'. Более общий пример: если 'd1', 'd2', ..., 'dN' содержат результаты работы комманд 'diff -e old new1', 'diff -e new1 new2', ..., 'diff -e newN-1 newN' соответственно, то команда '(cat d1 d2 ... dN && echo w) | ed -old' редактирует файл для создания копии 'newN'.

Подробное описание 'ed'-формата

'Ed'-формат вывода состоит из одного или более ханков различий. Изменения ближайшие к концу файлов идут первыми, так чтобы команды меняющие номера строк не влияли на интерпретацию 'ed' номеров строк в последующих командах. Ханки в 'ed'-формате выглядят так:

      CHANGE-COMMAND   
      TO-FILE-LINE   
      TO-FILE-LINE...   
      .    
Поскольку 'ed' использует одиночную точку в строке текста как признак окончания ввода, GNU 'diff' защищает строки изменений, которые содержат одиночную точку в строке, заменяя их на строки с двумя точками, и выводя команду для замены двух точек на одну. Формат 'ed' не может представить незавершенную строку, так что если второй файл кончается незавершенной строкой, 'diff' выдает сообщение об ошибке, после чего позволяет себе добавление символа новой строки.

Существует три типа команд, изменяющих текст. Каждая состоит из номера строки или раздленного запятыми списка строк первого файла и символа, показывающего какой вид изменения нужно сделать. Все номера строк оригинальны для каждого файла. Типы команд следующие:

'La'

Добавить текст из второго файла после строки L первого файла. Например, '8a' значит добавить следующие строки после строки 8 первого файла.

'Rc'

Заменить строки из промежутка R в первом файле следующими строками. Команда подобна комбинации удаления и вставки, но более компактна. Например, '5,7c' значит заменить строки 5-7 первого файла на текст из второго файла.

'Rd'

Удалить строки из промежутка R в первом файле. Например, '5,7d' значит удалить строки 5-7 из первого файла.

Пример командного файла для 'ed'

Далее представлен результат работы команды 'diff -e lao tzu' (см. "Два образца входных файлов", для полного текста этих файлов):

      11a   
      They both may be called deep and profound.   
      Deeper and more profound,   
      The door of all subtleties!   
      .   
      4c   
      The named is the mother of all things.   
   
      .   
      1,2d     

Прямые командные файлы для 'ed'

'diff' позволяет выводить результаты работы в формате командного файла для 'ed', но с прямым (от первого к последнему) порядком ханков. Формат команд также немного изменен: командные символы предшествуют списку изменяемых строк, строки в списке разделяются пробелами, и не делается попыток прояснить строки ханков, состосящие из одного периода. Подобно 'ed'-формату, прямой 'ed'-формат не может отображать неполные строки.

Прямой 'ed'-формат не очень полезен, так как ни 'ed', ни 'patch' не могут применять "изменения" этого формата. Он существует главным образом для совместимости с более старыми версиями 'diff'. Чтобы задать его используйте опцию '-f' или '--forward-ed'.

Командный файл для RCS

Формат вывода RCS разработан специально для использования Системой управления изменениями (Revision Control System - RCS), представляющей из себя набор свободно распространяемых программ, используемых для организации хранения разных версий и систем файлов. Используйте опцию '-n' или '--rcs' для задания этого формата вывода. Он похож на прямой 'ed'-формат (см. "Прямые командные файлы для ed".), но позволяет отображать произвольные изменения в контексте файлов, потому что избегает проблем прямого 'ed'-формата со строками, состоящими из одной точки и неполными строками. Вместо того, чтобы кончать разделы текста строками, состоящими из одного периода, каждая команда указывает на номер строки с которой имеет дело; вместо команды 'c' используется комбинация из команд 'a' и 'd'. Кроме того, если второй файл кончается измененной неполной строкой, то выходной файл также заканчивается неполной строкой.

Далее представлен результат работы команды 'diff -n lao tzu' (см. "Два образца входных файлов" , для полного текста этих файлов):

      d1 2   
      d4 1   
      a4 2   
      The named is the mother of all things.   
   
      a11 3   
      They both may be called deep and profound.   
      Deeper and more profound,   
      The door of all subtleties!   

3.7 Слияние файлов с if-then-else

Возможно использование 'diff' для слияния двух файлов - текстов программ на С. Результат работы 'diff' в этом формате будет содержать все строки обоих файлов. Строки общие для файлов отображаются только один раз; разные части разделяются с помощью директив препроцессора C '#ifdef NAME' или '#ifndef NAME', '#else', и '#endif'. При компиляции, таким образом, можно выбирать какую версию использовать определяя или оставляя неопределенным макрос NAME.

Для слияния двух файлов, используйте 'diff' с опцией '-D NAME' или '--ifdef=NAME'. Аргумент NAME - это идентификатор, который будет использовать препроцессор C в директивах '#ifdef' и '#ifndef'.

Например, при изменении первоначального

 'wait (&s)'   
на
 'waitpid (-1,&s,0)'   
и слиянии старого и нового файлов с помощью опции '--ifdef=HAVE_WAITPID', конечная часть вашего текста может выглядить так:

          do {   
      #ifndef HAVE_WAITPID   
              if ((w = wait (&s)) < 0  &&  errno != EINTR)   
      #else /* HAVE_WAITPID */   
              if ((w = waitpid (-1, &s, 0)) < 0  &&  errno != EINTR)   
      #endif /* HAVE_WAITPID */   
                  return w;   
          } while (w != child);   
Можно определить формат для языка отличного от C используя форматы групп строк и строчные форматы, как будет описаны далее.

Форматы групп строк

Форматы групп строк позволяют Вам задать форматы, работающие для многих приложений, которые позволяют ввод структурами if-then-else, включая языки программирования и форматирования текста. Формат групп строк задает формат вывода для соприкасающихся групп сходных строк.

Например, следующая команда сравнивает TeX файлы 'old' и 'new' и выводит единый файл, в котором старые районы окружены строками '\begin{em}'-'\end{em}', а новые районы - строками '\begin{bf}'-'\end{bf}':

      diff \   
         --old-group-format='\begin{em}   
      %<\end{em}   
      ' \   
         --new-group-format='\begin{bf}   
      %>\end{bf}   
      ' \   
         old new   
Следующая команда эквивалентна предыдущему примеру, но немного более многословна, потому что она раскрывает заданные по умолчанию форматы групп строк.

      diff \   
         --old-group-format='\begin{em}   
      %<\end{em}   
      ' \   
         --new-group-format='\begin{bf}   
      %>\end{bf}   
      ' \   
         --unchanged-group-format='%=' \   
         --changed-group-format='\begin{em}   
      %<\end{em}   
      \begin{bf}   
      %>\end{bf}   
      ' \   
         old new   
Далее представлен более сложный пример, который выдает список различий с заголовками, содержащими номера строк в стиле "прямой английский".

      diff \   
         --unchanged-group-format='' \   
         --old-group-format='-------- %dn line%(n=1?:s) deleted at %df:   
      %<' \   
         --new-group-format='-------- %dN line%(N=1?:s) added after %de:   
      %>' \   
         --changed-group-format='-------- %dn line%(n=1?:s) changed at %df:   
      %<-------- to:   
      %>' \   
         old new   
Чтобы задать формат групп строк, используйте 'diff' с одной из показанных ниже опций. Вы можете задать до 4 форматов групп строк, по одной для каждого вида группы. Следует заключать FORMAT в кавычки, так как он обычно содержит метасимволы оболочки.
`--old-group-format=FORMAT'

Эти группы строк являются ханками, содержащими только строки из первого файла. Заданный по умолчанию формат старых групп - то же самое, что формат измененных групп, если он задан; иначе это формат, выдающий группы строк как они есть.

`--new-group-format=FORMAT'

Эти группы строк являются ханками, содержащими только строки второго файла. Заданный по умолчанию формат новых групп - то же самое, что формат изменненых групп, если он задан; в противном случае, это формат, выдающий группы строк, как они есть.

`--changed-group-format=FORMAT'

Эти группы строк являются ханками, содержащими строки из обоих файлов. Заданный по умолчанию формат измененных групп - это комбинация из форматов старых и новых групп.

`--unchanged-group-format=FORMAT'

Эти группы строк содержат строки, общие для обоих файлов. Заданный по умолчанию формат неизмененных групп - это формат, выдающий группы строк, как они есть.

В формате групп строк обычные символы представляют сами себя; спецификация изменения начинается с '%' и имеет одну из следующих форм.
'%<'

обозначает строки первого файла, включая символ новой строки. Каждая строка форматирована в соответствии с форматом старых строк (см. Строчные формат::.).

'%>'

обозначает строки второго файла, включая символы новой строки. Каждая строка форматирована в соответствии с форматом новых строк.

'%='

обозначает строки, общие для обоих файлов, включая завершающие символы перехода на новую строку. Каждая строка форматируется в соответствии с форматом неизмененных строк

'%%'

обозначает '%'.

'%c'C''

где С - некоторый символ; обозначает этот символ. C не может быть символом обратная косая черта '/' или апострофом. Например, '%c':'' обозначает двоеточие, даже внутри then-части формата if-then-else, которая обычно завершается двоеточием.

'%c'\O''

где O - строка из 1, 2 или 3 восьмеричных цифр; обозначает символ, десятичный код которого O. Например, '%c'\0'' обозначает символ с кодом ноль.

'FN'

где F - строка форматирования в стиле функции языка Си 'printf', а N - один из следующих символов, обозначающее значение, которое должно быть отформатировано в соответствии с F

'e'

Номер строки, предшествующей группе в старом файле.

'f'

Номер первой строки в группе из старого файла; равен E + 1.

'l'

Номер последней строки в группе из старого файла.

'm'

Номер строки, следующей за группой в старом файле; равен L + 1.

'n'

Количество строк в группе из старого файла; равно L - F + 1.

'E, F, L, M, N'

То же для строк в новом файле.

Спецификаторами в строке форматирования типа `printf' могут быть `%d', `%o', `%x', или '%X', задавая вывод десятичный, восьмеричный, вывод прописными и строчными шестнадцатиричными соответственно. После символа '%' следующая опция может появиться в следующей последовательности: '-', задающий на левое выравнивание; целое число, задающее минимальную ширину поля; и точка, за которой следует возможно отсутствующее целое, задающее минимальное число знаков. Например, '%5dN' печатает число новых строк в группе в поле шириной 5 символов, используя 'printf' формат '"%5d"'.

'(A=B?T:E)'

Если A равно B, то T, иначе E. A и B оба должны быть либо десятичными константами, либо единственным символом, интерпретируемым подобно вышеописанному. Этот вид формата эквивалентен T, если значение A равно значению B; в противном случае он эквивалентен E.

Например, '%(N=0?no:%dN) line%(N=1?:s)' эквивалентно 'no lines', если N (количество строк в группе из нового файла) равно 0, '1 line', если N равно 1, и '%dN lines' в противном случае.

Строчные форматы

Строчные форматы управляют, каким образом каждая строка, взятая из входного файла, выводится как часть группы строк в формате if-then-else.

Например, следующая команда выводит текст с одной колонкой индикатора изменений слева от текста. Первая колонка выводит '-' для удаленных строк, '|' - для добавленных строк, и пробел - для неизмененных строк. Форматы содержат символы новых строк, там, где допустим их вывод.

      diff \   
         --old-line-format='-%l   
      ' \   
         --new-line-format='|%l   
      ' \   
         --unchanged-line-format=' %l   
      ' \   
         old new   
Чтобы задать строчный формат, используйте одну из следующих опций. Следует заключать FORMAT в кавычки, поскольку он часто содержит метасимволы оболочки.
`--old-line-format=FORMAT'

форматирует только строки из первого файла.

`--new-line-format=FORMAT'

форматирует только строки из второго файла.

`--unchanged-line-format=FORMAT'

форматирует строки, общие для обоих файлов.

`--line-format=FORMAT'

форматирует все строки; т.е. имеет тот же эффект, что и одновременное применение трех предыдущих опций.

В строчном формате обычные символы представляют сами себя; спецификации изменений начинаются с символа '%' и имеют одну из следующих форм.

'%l'

обозначает содержимое строки, не включая прилегающих к ней символов перехода на новую строку (если они есть). Для этого формата все равно, является ли строка неполной (см. "Неполные строки").

'%L'

обозначает содержмое строки, включая прилегающие к ней символов перехода на новую строку (если они есть). Если строка неполна, этот формат сохраняет ее такой, как она есть.

'%%'

обозначает '%'.

'%c'C''

где С - некоторый символ. С не может быть символом "обратная косая черта" или апострофом. Например, '%c':'' обозначает двоеточие.

'%c'\O''

где O - строка из 1, 2 или 3 восьмеричных цифр, обозначает символ, десятичный код которого O. Например, '%c'\0'' обозначает символ с кодом ноль.

'Fn'

где F - строка форматирования в стиле функции языка Си 'printf'; обозначает строки с номером n, форматированные с помощью F. Например, '%.5dn' печатает строку с номером n, пользуясь форматом '"%.5d"'. (См. подробнее "Форматы групп строк").

Заданный по умолчанию формат строк - '%l' с символом новой строки на конце.

Если входной текст содержит символы табуляции, и необходимо, чтобы это сохранилось в результирующем тексте, следует следить за тем, чтобы '%l' и '%L' в строчном формате следовали только после табуляции (например, ставить символ табуляции перед каждым '%l' или '%L'), или использовать опции '-t' или '--expand-tabs'.

Определенные одновременно, строчный формат и формат групп строк позволяют задать много разных форматов. Например, следующая команда использует формат, похожий на нормальный формат 'diff'. С помощью изменений этой команды можно получить полный контроль над выводом информации 'diff'.

      diff \   
         --old-line-format='< %l   
      ' \   
         --new-line-format='> %l   
      ' \   
         --old-group-format='%df%(f=l?:,%dl)d%dE   
      %<' \   
         --new-group-format='%dea%dF%(F=L?:,%dL)   
      %>' \   
         --changed-group-format='%df%(f=l?:,%dl)c%dF%(F=L?:,%dL)   
      %<--­   
      %>' \   
         --unchanged-group-format='' \   
         old new   

Детальное описание формата if-then-else

Для строк общих для обоих файлов, 'diff' использует формат неизмененных групп строк. Для каждого ханка различий в объединяющем формате вывода, если ханк содержит только строки из первого файла, 'diff' использует формат старых групп строк; если ханк содержит только строки из второго файла, 'diff' использует формат новых групп; иначе, 'diff' использует формат измененных групп.

Формат старых, новых и неизмененных строк задает формат вывода из строк первого файла, строк второго файла и строк общих для обоих файлов соответственно.

Опция '--ifdef=NAME' эквивалента следующей последовательности опций, использующих синтаксис оболочки:

      --old-group-format='#ifndef NAME   
      %<#endif /* not NAME */   
      ' \   
      --new-group-format='#ifdef NAME   
      %>#endif /* NAME */   
      ' \   
      --unchanged-group-format='%=' \   
      --changed-group-format='#ifndef NAME   
      %<#else /* NAME */   
      %>#endif /* NAME */   
      '   
Следует внимательно следить за правильностью вложенности в выходном Например, при использовании опций '-D NAME' или '--ifdef=NAME', необходимо следить, чтобы различающиеся строки, содержащие любые из директив препроцессора C: '#ifdef', '#ifndef', '#else', '#elif', или '#endif' размещались в нужных местах и попарно соответствовали по вложенности. Если это не так, нужно внести изменения вручную. Лучше всего отслеживать результирующйи код всегда, чтобы быть уверенным, что вы получили то, что ожидали; в зависимости от того, как были получены входные файлы, выходной файл может содержать повторяющиеся строки или другие ошибки в коде.

Опция 'patch' '-D NAME' работает также как и опция 'diff' '-D NAME', за исключением того, что она имеет дело с файлом и diff-ом для воспроизведения единого файла (см. Опции patch::).

Пример формата if-then-else

Далее представлен результат работы 'diff -DTWO lao tzu' (см. Два образца входных файлов::, для полного текста этих двух файлов):

      #ifndef TWO   
      The Way that can be told of is not the eternal Way;   
      The name that can be named is not the eternal name.   
      #endif /* not TWO */   
      The Nameless is the origin of Heaven and Earth;   
      #ifndef TWO   
      The Named is the mother of all things.   
      #else /* TWO */   
      The named is the mother of all things.   
  
      #endif /* TWO */   
      Therefore let there always be non-being,   
        so we may see their subtlety,   
      And let there always be being,   
        so we may see their outcome.   
      The two are the same,   
      But after they are produced,   
        they have different names.   
      #ifdef TWO   
      They both may be called deep and profound.   
      Deeper and more profound,   
      The door of all subtleties!   
      #endif /* TWO */   

Вперед Назад Содержание