close

Ero

Siirry navigointiin Siirry hakuun

Laskennassa  diff on tiedostojen vertailuapuohjelma, joka näyttää eron kahden tiedoston välillä. Tämä ohjelma tulostaa rivi riviltä tiedostoon tehdyt muutokset (tekstitiedostoille). Nykyaikaiset toteutukset tukevat myös binääriä . Apuohjelman tulostetta kutsutaan "diff"ksi tai yleisemmin korjaustiedostoksi , koska sitä voidaan käyttää korjaustiedoston kanssa . Muiden tiedostojen vertailuapuohjelmien tulosta kutsutaan usein myös nimellä "diff".

Historia

Diff-apuohjelma kehitettiin 1970-luvun alussa Unix -käyttöjärjestelmää varten , joka oli AT&T Bell Labsin tekemä Murray Hillissä, New Jerseyssä. Lopullisen version, joka jaettiin Unix 5:llä vuonna 1974, kirjoitti kokonaan Douglas McIlroy .

McIlroyn työtä edelsi ja vaikutti Steve Johnsonin GECOS-vertailuohjelma ja Mike Leskin proof-ohjelma. Todistus on myös peräisin Unixista ja, kuten diff, teki rivi riviltä muutoksia ja jopa käytti kulmasulkuja (">" ja "<") kuvaamaan rivin lisäyksiä ja poistoja ohjelman ulostulossa. Näissä varhaisissa sovelluksissa käytettyä heuristiikkaa pidettiin kuitenkin epäluotettavina. Vertailutyökalun mahdollinen käyttökelpoisuus sai McIlroyn tutkimaan ja kehittämään tehokkaamman työkalun, jota voitaisiin käyttää useissa eri tehtävissä, mutta joka toimisi hyvin PDP-11-laitteiston käsittely- ja kokorajoitusten puitteissa. Hänen lähestymistapansa ongelmaan oli seurausta yhteistyöstä Bell Labsin ihmisten kanssa, mukaan lukien Alfred Ahon, Elliot Pinsonin, Jeffrey Ullmanin ja Harold S. Stonen kanssa.

Algoritmi

Diff:n toiminta perustuu pisimmän yhteisen osasekvenssin löytämiseen ( LCS-ongelma) .  Esimerkiksi elementtejä on kaksi sarjaa:

       abcdfghjqz
       abcdefgijkrxyz

ja sinun on löydettävä pisin elementtisarja, joka esitetään molemmissa sarjoissa samassa järjestyksessä. Tämä tarkoittaa, että on löydettävä uusi sekvenssi, joka voidaan saada ensimmäisestä sekvenssistä poistamalla joitakin elementtejä tai toisesta sekvenssistä poistamalla muita elementtejä. Tässä tapauksessa järjestys on

       abcdfgjz

Kun olet saanut suurimman yhteisen sekvenssin, on jäljellä vain pieni askel ennen erotuskaltaisen lähdön saamista:

       ehikqrxy
       + - + + - + + +

Käyttö

diff kutsutaan komentoriviltä kahden tiedoston nimellä argumentteina: diff original new . Komennon tulos on muutokset, jotka on tehtävä alkuperäiseen lähdetiedostoon, jotta uusi tiedosto saadaan uutena. Jos alkuperäinen ja uusi ovat hakemistoja, diff-tunnusta käytetään automaattisesti jokaiseen tiedostoon, joka on olemassa molemmissa hakemistoissa. Kaikki tämän artikkelin esimerkit käyttävät seuraavia kahta tiedostoa, alkuperäistä ja uutta :

alkuperäinen:

Tämä osa asiakirjaa
pysyi ennallaan
versiosta toiseen. Jos
hänessä ei ole muutosta
ei pitäisi näyttää.
Muuten se ei auta
optimaalisen johtopäätös 
tuotettu
muutoksia.

Tämä kappale sisältää
vanhentunutta tekstiä.
Se poistetaan
pian.

Tämä asiakirja
täytyy olla
oikeinkirjoituksen tarkistus.
Toisaalta virhe
Sanalla sanoen - ei maailmanloppu.
Loput kappaleesta
ei vaadi muutoksia.
Uusi teksti voi
lisää asiakirjan loppuun.

Uusi:

Tämä on tärkeä huomio!
Siksi sen pitäisi
sijaita
tämän alussa
asiakirja!

Tämä osa asiakirjaa
pysyi ennallaan
versiosta toiseen. Jos
hänessä ei ole muutosta
ei pitäisi näyttää.
Muuten se ei auta
optimaalisen johtopäätös 
tiedon määrä.
 
Tämä asiakirja
täytyy olla
oikeinkirjoituksen tarkistus.
Toisaalta virhe
Sanalla sanoen - ei maailmanloppu.
Loput kappaleesta
ei vaadi muutoksia.
Uusi teksti voi
lisää asiakirjan loppuun.

Tämä kappale sisältää
tärkeitä lisäyksiä
tälle asiakirjalle.

Diff alkuperäinen uusi komento tuottaa seuraavan normaalin diff - ulostulon :

0a1.6
 > Tämä on tärkeä huomio!
 > Siksi pitäisi
 > sijaita
 > tämän alussa
 > asiakirja!
 >
 8.14c14
 <tuotannon määrä
 <muutoksia.
 <
 < Tämä kappale sisältää
 < vanhentunutta tekstiä.
 < Se poistetaan
 < lähitulevaisuudessa.
 ---
 > tiedon määrä.
 17c17
 < täytyy tehdä
 ---
 > täytyy tehdä
 24-25.28
 >
 > Tämä kappale sisältää
 > tärkeitä lisäyksiä
 > tälle asiakirjalle.

Tässä perinteisessä tulostusmuodossa a tarkoittaa lisättyä ( englanninkielisestä  add ), d tarkoittaa poistettua , c tarkoittaa muutettua . Kirjaimia a, d tai c edeltävät lähdetiedoston rivinumerot, joita seuraa kohdetiedoston rivinumerot. Jokaista lisättyä, poistettua tai muokattua riviä edeltää kulmasulkeet .

Oletusarvoisesti lähde- ja kohdetiedostoille yhteisiä rivinumeroita ei ole määritetty. Siirretyt rivit näytetään lisättyinä uuteen sijaintiinsa ja poistettuina aiemmasta sijainnistaan. [yksi]

Vaihtoehdot

Useimmat diff-toteutuksista ovat pysyneet ulkoisesti muuttumattomina vuodesta 1975 lähtien. Muutokset sisältävät parannuksia pääalgoritmiin, uusien komentonäppäinten lisäämisen ja uudet tulostusmuodot. Perusalgoritmi on hahmoteltu Eugene W. Myersin teoksissa An O(ND) Difference Algorithm ja sen variaatiot [2] ja Webb Millerin ja Myersin [3] A File Comparison Program -ohjelmassa . Algoritmi on itsenäisesti keksitty ja kuvattu E. Ukkosen julkaisussa Algorithms for Approximate String Matching [4] . Diff-ohjelman ensimmäiset versiot suunniteltiin vertaamaan tekstitiedostojen rivejä käyttämällä rivinvaihtomerkkiä rivierottimena. 1980-luvulla binääritiedostojen tuki johti muutoksiin ohjelman toiminnassa ja toteutuksessa.

Muokkaa skriptiä

Muokkauskomentosarja voidaan luoda nykyaikaisilla diff-versioilla valitsimella -e . Esimerkkimme tulos näyttää tältä:

24a

Tämä kappale sisältää
tärkeitä lisäyksiä
tälle asiakirjalle.
.
17c
täytyy olla
.
8.14c
tiedon määrä.
.
0a
Tämä on tärkeä huomio!
Siksi sen pitäisi
sijaita
tämän alussa
asiakirja!

.

Jos haluat käyttää tuloksena saatua komentosarjaa muuntaaksesi alkuperäisen tiedoston uuteen tiedoston tilaan , meidän on lisättävä kaksi riviä skriptin loppuun: toinen sisältää komennon w (kirjoita), toinen - q (sulje). Esimerkiksi niin . Tässä olemme nimenneet diff-tiedoston mydiff . Muutos tapahtuu, kun annamme komennon . printf "w\nq\n" >> mydiffed -s original < mydiff

Kontekstimuoto

BSD - versio 2.8 (julkaistu heinäkuussa 1981) esitteli kontekstimuodon ( -c ) ja mahdollisuuden kulkea rekursiivisesti tiedostojärjestelmän hakemistopuussa ( -r ).

Kontekstimuodossa muuttuneet rivit näytetään yhdessä muuttumattomien rivien kanssa ennen ja jälkeen muutettua fragmenttia. Lisäämällä kuinka monta riviä ei vaikuta, saadaan korjaustiedoston konteksti . Konteksti , joka koostuu koskemattomista riveistä, toimii viitteenä määritettäessä muokattavan fragmentin sijaintia kohdetiedostossa, vaikka muokattujen rivien rivinumerot lähde- ja kohdetiedostoissa eivät täsmää. Kontekstimuoto on ihmisten luettavampi ja luotettavampi korjaustiedostoa asetettaessa, ja tuloste otetaan korjaustiedoston syötteeksi .

Käyttäjä voi asettaa muuttumattomien rivien määrän ennen ja jälkeen muokattua fragmenttia ja se voi olla jopa nolla, mutta yleensä oletusarvo on kolme riviä. Jos fragmentin vaikuttamattomien juovien konteksti on päällekkäinen viereisen fragmentin kanssa, diff välttää vaikuttamattomien juovien kopioimisen ja yhdistää viereiset fragmentit yhdeksi.

Alkuperäisen uuden komennon diff -c tulos on:

*** /polku/alkuperäiseen ''aikaleimaan''
 --- /polku/uuteen ''aikaleimaan''
**************
*** 1,3 ****
--- 1,9 ---- 
+ Tämä on tärkeä huomautus! 
+ Joten sen 
+ pitäisi sijaita 
+ tämän + asiakirjan + alussa 
! 
+
  Tämä osa asiakirjaa
  pysyi ennallaan
  versiosta toiseen. Jos
**************
*** 5,20 ****
  ei pitäisi näyttää.
  Muuten se ei auta
  optimaalisen johtopäätös
! tuotettu määrä 
! muutoksia. 
! 
! Tämä kappale sisältää 
! vanhentunutta tekstiä. 
! Hänet poistetaan 
! pian.
  
  Tämä asiakirja
! täytyy olla
  oikeinkirjoituksen tarkistus.
  Toisaalta virhe
  Sanalla sanoen - ei maailmanloppu.
--- 11.20 ----
  ei pitäisi näyttää.
  Muuten se ei auta
  optimaalisen johtopäätös
! tiedon määrä.
  
  Tämä asiakirja
! täytyy olla
  oikeinkirjoituksen tarkistus.
  Toisaalta virhe
  Sanalla sanoen - ei maailmanloppu.
**************
*** 22.24 ****
--- 22.28 ----
  ei vaadi muutoksia.
  Uusi teksti voi
  lisää asiakirjan loppuun.
++ 
Tämä kappale sisältää 
tärkeitä lisäyksiä 
+ tähän asiakirjaan.

Universaali muoto

Universaali muoto (tai unidiff ) sisältää kontekstimuotoon tehdyt tekniset parannukset, mutta tekee eron vanhan ja uuden tekstin välillä tiiviimmällä tavalla. Yleistä muotoa kutsutaan yleensä komentorivivalitsimen " -u " avulla . Tätä tulostetta käytetään usein ohjelmien korjaustiedostona . Monet projektit vaativat erityisesti, että "diffs" lähetetään heille yleisessä muodossa, mikä tekee yleisestä muodosta yleisimmän ohjelmistokehittäjien välisen vaihdon.

Universaalit kontekstidiffit kehitti ensimmäisen kerran Wayne Davison elokuussa 1990 ( unidiff esiintyy comp.sources.misc:n luvussa 14). Stallman lisäsi universaalin muototuen GNU Projectin diff-apuohjelmaan kuukautta myöhemmin, ja tämä toiminto debytoi GNU diff 1.15:ssä, joka julkaistiin tammikuussa 1991. GNU diff on sittemmin yleistänyt kontekstiformaatin mahdollistaakseen mielivaltaisen erojen muotoilun.

Yleisen muodon tiedosto alkaa samoilla kahdella rivillä kuin kontekstimuoto, paitsi että alkuperäinen tiedosto alkaa kirjaimella --- ja uusi tiedosto alkaa kirjaimella " +++ ". Niitä seuraa yksi tai useampi muutettu katkelma , jotka sisältävät rivi riviltä muutoksia tiedostoihin. Muutoksettomat rivit alkavat välilyönnillä, lisätyt rivit alkavat plusmerkillä, poistetut rivit alkavat miinusmerkillä.

Fragmentti alkaa aluetiedoilla ja sitä seuraa välittömästi lisätyt rivit, poistetut rivit ja mikä tahansa määrä kontekstirivejä. Aluetietoja ympäröi kaksinkertainen @ -merkki ja ne ketjutetaan yhdelle riville, toisin kuin kaksi riviä muodossa ( kontekstimuoto ). Aluetiedot ovat seuraavassa muodossa:

@@ -l,s +l,s @@ valinnainen osion otsikko

Aluetiedot koostuvat kahdesta osasta. Alkuperäisen tiedoston osa alkaa miinuksella ja uuden tiedoston osa plussalla. Jokainen osa on muodossa l, s , jossa l  on sen rivin numero, jolla aloitamme, ja s  on niiden rivien lukumäärä, joita on muutettu kunkin tiedoston nykyisessä fragmentissa (eli ensimmäisessä tapauksessa tämä on välilyönnillä ja miinuksella alkavien tulosrivien summa, toisessa - välilyönnillä ja plussalla alkavien rivien summa). Monissa GNU diff:n versioissa pilkku ja lopussa olevat s voidaan jättää pois kustakin alueesta. Tässä tapauksessa s on oletuksena 1. Huomaa, että ainoa hyödyllinen arvo l :lle yksin  on ensimmäisen alueen rivinumero, muut arvot voidaan laskea erotusarvosta.

Alkuperäisen tiedoston alueen fragmentin on oltava fragmentin kaikkien kontekstien ja poistettujen (mukaan lukien muokattujen) rivien summa. Uuden tiedoston alueen fragmentin on sisällettävä fragmentin kaikkien kontekstien ja lisättyjen (mukaan lukien muokattujen) rivien summa.

Aluefragmenttia voi edeltää sen osan tai toiminnon otsikko, jonka osa fragmentti on. Tämä on yleensä hyödyllistä luettaessa itse katkelmaa. Kun luot erotusta GNU:lla, erotusotsikko määräytyy säännöllisen lausekkeen [5] avulla .

Jos riviä on muutettu, se näytetään sekä poistettuna että lisättynä. Koska poistetut ja lisätyt rivit ovat vierekkäisissä fragmenteissa, nämä rivit näytetään vierekkäin [6] . Esimerkiksi:

- Tarkista tämä asiakirja. Päällä
+tarkista tämä asiakirja. Päällä

Komento diff -u alkuperäinen uusi tuottaa seuraavan tulosteen:

--- /polku/alkuperäiseen ''aikaleimaan'' 
+++ /polku/uuteen ''aikaleimaan'' 
@@ -1.3 +1.9 @@ 
+Tämä on tärkeä huomautus! 
+Sen vuoksi sen tulisi 
sijaita +asiakirjan + 
alkussa 
! 
+
 Tämä osa asiakirjaa
 pysyi ennallaan
 versiosta toiseen. Jos
@@ -5.16 +11.10 @@
 ei pitäisi näyttää.
 Muuten se ei auta
 optimaalisen johtopäätös
- tehtyjen 
muutosten määrä. 
- 
-Tämä kappale sisältää 
vanhentunutta tekstiä. 
-Se poistetaan 
-lähitulevaisuudessa. 
+ tiedon määrä.
 
 Tämä asiakirja
- täytyy tehdä 
+ täytyy tehdä
 oikeinkirjoituksen tarkistus.
 Toisaalta virhe
 Sanalla sanoen - ei maailmanloppu.
@@ -22,3 +22,7 @@
 ei vaadi muutoksia.
 Uusi teksti voi
 lisää asiakirjan loppuun.
++ 
Tämä kappale sisältää 
+tärkeitä lisäyksiä 
+tälle asiakirjalle.

Huomaa, että välilehtiä käytetään erottamaan tiedostonimet oikein aikaleimoista. Tämä on näkymätön näytöllä ja voi kadota, kun kopioit/liität konsolista.

Diff-muotoihin on olemassa useita muutoksia ja laajennuksia, joita eri ohjelmat käyttävät ja ymmärtävät. Esimerkiksi jotkin versionhallintajärjestelmät , kuten Subversion , määrittävät versionumeron, "työkopion" tai minkä tahansa muun kommentin eron otsikon aikaleiman lisäksi.

Joidenkin ohjelmien avulla voit luoda eroja useille eri tiedostoille ja yhdistää ne yhdeksi käyttämällä otsikkoa kullekin muutetulle tiedostolle, joka saattaa näyttää suunnilleen tältä:

Hakemisto: polku/tiedosto.cpp

Erikoistyyppisiä tiedostoja, jotka eivät pääty rivinvaihtoon, ei tueta. Unidiff-apuohjelma tai POSIX-diff-standardi eivät määrittele, kuinka tällaisia ​​tiedostoja käsitellään (itse asiassa tämän tyyppiset tiedostot eivät ole "tekstiä" POSIX [7] -määritelmässä ).

Paikkausohjelma ei tiedä mitään diff -komennon erikoistulosteen toteutuksesta.

Katso myös

Muistiinpanot

  1. David MacKenzie, Paul Eggert ja Richard Stallman. Tiedostojen vertailu ja yhdistäminen GNU Diffin ja  Patchin kanssa . – 1997.
  2. E. Myers. O(ND ) -eroalgoritmi ja sen muunnelmat   // Algorithmica  (Englanti) : päiväkirja. - 1986. - Voi. 1 , ei. 2 . - s. 251-266 .
  3. Webb Miller ja Eugene W. Myers. Tiedostojen vertailuohjelma // Ohjelmisto - Käytäntö ja kokemus. - 1985. - T. 15 , nro 11 . - S. 1025-1040 .
  4. E. Ukkonen.  Algoritmit likimääräiseen merkkijonosovitukseen //  Tiedot ja laskenta  (Englanti) : päiväkirja. - 1985. - Voi. 64 . - s. 100-118 .
  5. 2.2.3 Arkistoitujen osien erojen näyttäminen 26. toukokuuta 2013 Wayback Machinessa , GNU diffutils  manual
  6. Unified Diff Format Arkistoitu 5. huhtikuuta 2013 Wayback Machinessa , kirjoittanut Guido van Rossum , 14. kesäkuuta  2006
  7. http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_205 Arkistoitu 29. huhtikuuta 2013 Wayback Machine -osiossa 3.205 

Linkit