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


28

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

[myPrompt]$ cat file1
apples
oranges
[myPrompt]$ cat file2 
oranges
apples
[myPrompt]$ diff file1 file2
1d0
< apples
2a2
> apples

Чи може хтось пояснити вищезазначений криптовалют із розл.

  1. Чому на виході взагалі не згадується про "апельсини"?
  2. Що означає 1d0і що 2a2означає?

З цієї відповіді я розумію, що:

"<" означає, що рядок відсутній у file2, а ">" означає, що рядок відсутній у file1

Але НЕ пояснює, чому апельсини відсутні у виході.


12
Оскільки orangesце найбільша спільна частина між двома файлами, тож, що ви отримуєте, це найкоротший спосіб виразити відмінності між ними.
Стефан Шазелас

10
А якщо ви хочете більше читати вихід, просто використовуйте diff -u file1 file2замість цього. Так називається формат "уніфікований розл." Оригінальний формат diff мав бути дуже компактним, але уніфікований diff має бути набагато легше для читання.
godlygeek

4
@godlygeek Ordiff -y file1 file2
user80551

Відповіді:


27

Щоб зрозуміти звіт, пам’ятайте, що diffце прописи, що описують, які зміни потрібно внести в перший файл ( file1), щоб він був таким же, як і другий файл ( file2).

Зокрема, dв 1d0засобах видалення та aв 2a2засобах додавання .

Таким чином:

  • 1d0означає, що рядок 1 повинен бути видалений у file1( apples). 0у 1d0значенні рядок 0 - це те, де вони з'явилися б у другому файлі ( file2), якби вони не були видалені. Це означає, що при зміні file2на file1(назад) додавати рядок 1 file1після рядка 0 file2.
  • 2a2означає додавати другий рядок ( oranges) від file2другого рядка file1(після видалення першого рядка в file1, orangesпереключеного на рядок 1)

що 0в 1d0?
Geek

@Geek дивись мою редакцію
хаос

1
@Geek Але будьте обережні, що можуть зробити вузли в мозку =)
хаос

це справді почало робити вузли :-)
Geek

13

Розглянемо ці файли:

file1:

# cat file1
apples
pears
oranges
peaches

file2:

# cat file2
oranges
apples
peaches
ananas
banana

Як diffпрацює, враховуючи це на замовлення:

  1. diffчитає перший блок рядків file1і file2і намагається знайти рівні лінії:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      -------------------------------
    ->oranges    ->oranges
      peaches      apples
                   peaches
                   ananas
                   banana
    
  2. Тепер він буде пропускати всі рядки, які є рівними в обох файлах, що якраз orangesу цьому випадку:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
      -------------------------------
    ->peaches    ->apples
                   peaches
                   ananas
                   banana
    
  3. Тепер знайдіть інший набір подібних ліній та роздрукуйте відмінності:

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      -------------------------------
    ->peaches    ->peaches
                   ananas
                   banana
    
  4. Пропустіть подібні лінії

      file1        file2        differences on left (<) or right side (>)
      apples                   <apples
      pears                    <pears 
      oranges      oranges
                   apples      >apples
      peaches      peaches
      -------------------------------
    ->           ->ananas
                   banana
    
  5. Знайдіть однакові лінії, якщо це можливо, та роздрукуйте відмінності:

    line_file1    file1    line_file2    file2        differences on left (<) or right side (>)
             1    apples                              <apples 
             2    pears                               <pears 
             3    oranges           1    oranges
                                    2    apples       >apples
             4    peaches           3    peaches
                                    4    ananas       >ananas
                                    5    banana       >banana
             -----------------------------------------------
    

Тепер, якщо я diff file1 file2:

# diff file1 file2
1,2d0
< apples
< pears
3a2
> apples
4a4,5
> ananas
> banana

Тепер просто пояснити, що diffозначає вихід:

Для того, щоб зробити file1рівним file2:

  • 1,2d0: Видалити ( d) лінії 1-2від file1і змінити лінію 0з file2відповідно
  • 3a2: Append ( a) до лінії 3від file1лінії 2зfile2
  • 4a4,5: Append до лінії 4з file1ліній 4-5відfile2

diffпорівнює file1з file2рядком за рядком і встановлює відмінності у тимчасовій пам'яті. Після file1 доведення file2 до першого появи рядка в file1, який також відбувається в file2, всі рядки, рівні до тих пір, поки різниця не згадана, часто позначається як ---. У цьому випадку існує лише одна подібна лінія, яка є oranges. Зауважте, що я сказав file1рівним file2, тому file1його розглядається відносно, file2а не навпаки.

У цьому випадку результат виходить відносно першого файлу file1.


2
Мені не подобається початкове пояснення: applesзустрічається в обох файлах так само добре.
АБО Mapper

1
@ORMapper Я змінив пояснення. Це зараз звучить чіткіше / краще :)?
полим

Не зовсім, зараз ви писали "є лише один подібний рядок, який є oranges". Неправильно: насправді є дві лінії, які не тільки схожі , але абсолютно однакові . Один з них читає oranges, другий читає apples. Крім того, ваше пояснення (суто на основі порядку) суперечить коментарю Стефана щодо питання (на основі довжини) - хто правильно?
АБО Mapper

@ORMapper Ви забули "У цьому випадку" та рядки до цього. Я мав на увазі, що на цьому кроці є лише одна схожа лінія. Я просто додам приклад до своєї відповіді, щоб можна було краще зрозуміти.
полим

1
@ORMapper Ви також можете навести приклад, який показує, що відповідь на основі довжини є правильною?
полим


8

Стандартний (старий) формат виводу відображатиме різницю між файлами без оточуючого тексту з областями, де файли відрізняються.

Наприклад: 1d0 <(видалити) означає, що яблука потрібно видалити з 1-го рядка file1, а 2a2 >(додати) означає, що яблука потрібно додати у file22-му рядку, щоб обидва файли могли бути зіставлені.

Документація, доступна на сайті, info diffпояснює це далі:

Показано відмінності без контексту

"Нормальний" diffвихідний формат показує кожну частину відмінностей без будь-якого оточуючого контексту. Іноді такий вихід є найяснішим способом побачити, як змінилися рядки, без захаращення сусідніх незмінних ліній (хоча ви можете отримати подібні результати з контекстом або уніфікованими форматами, використовуючи 0 рядків контексту). Однак цей формат більше не використовується широко для надсилання патчів; з цією метою контекстний формат і уніфікований формат є вищими. Нормальний формат є типовим для сумісності зі старими версіями diffта стандартом POSIX. Використовуйте --normalопцію, щоб чітко вибрати цей вихідний формат.

Детальний опис звичайного формату

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

 CHANGE-COMMAND
 < FROM-FILE-LINE
 < FROM-FILE-LINE...
 ---
 > TO-FILE-LINE
 > TO-FILE-LINE...

Існує три типи команд зміни. Кожен складається з номера рядка або розділеного комами рядка у першому файлі, одного символу, що вказує на вид зміни, яке потрібно внести, та номера рядка або розділеного комами рядка у другому файлі. Всі номери рядків - це оригінальні номери рядків у кожному файлі. Типи команд зміни:

LaR Додайте рядки в діапазоні R другого файлу після рядка L першого файлу. Наприклад, 8a12,15означає додавання рядків 12-15 файла 2 після рядка 8 файлу 1; або, якщо змінити файл 2 у файл 1, видалити рядки 12-15 файла 2.

FcT Замініть рядки в діапазоні F першого файлу рядками в діапазоні T другого файлу. Це як комбіноване додавання та видалення, але більш компактне. Наприклад, 5,7c8,10означає змінити рядки 5-7 файлу 1 для читання як рядки 8-10 файлу 2; або, якщо змінити файл 2 у файл 1, змінити рядки 8-10 файла 2 таким чином, щоб читати як рядки 5-7 файлу 1.

RdL Видаліть рядки в діапазоні R з першого файлу; рядок L - це те, де вони з'явилися б у другому файлі, якби вони не були видалені. Наприклад, 5,7d3означає видалити рядки 5-7 файлу 1; або, якщо змінюється файл 2 у файл 1, додайте рядки 5-7 файлу 1 після рядка 3 файлу 2.

Дивись також:


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

Наприклад:

$ diff -y file1 file2
apples                                <
oranges                             oranges
                                  > apples

$ diff -u file1 file2
@@ -1,2 +1,2 @@
-apples
 oranges
+apples
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.