Być może, jeśli masz plik, który kończy się bez nowej linii, i dodajesz inną linię, git musiałby pokazać, że poprzednia ostatnia linia uległa zmianie, ponieważ zawiera znak nowej linii jako część linii?
nafg
Odpowiedzi:
458
Wskazuje, że nie masz nowego wiersza (zwykle '\n'aka CR lub CRLF) na końcu pliku.
To po prostu ostatni bajt (lub bajty w systemie Windows) w pliku nie jest znakiem nowej linii.
Komunikat jest wyświetlany, ponieważ w przeciwnym razie nie można odróżnić pliku, w którym na końcu znajduje się nowa linia, a gdzie nie ma. Diff i tak musi wypisać nowy wiersz, inaczej wynik będzie trudniejszy do odczytania lub przetworzenia automatycznie.
Zauważ, że dobrym stylem jest zawsze umieszczanie nowego wiersza jako ostatniego znaku, jeśli pozwala na to format pliku. Ponadto, na przykład, w przypadku plików nagłówkowych C i C ++ jest to wymagane przez standard językowy.
Czy z ciekawości możesz wyjaśnić, dlaczego za dobry styl uważa się zawsze umieszczanie nowej linii za ostatnią postać? Edytuj: znaleziono tę dyskusję .
Paul Bellora,
84
@PaulBellora Historycznie była to decyzja podjęta przez standard języka C stackoverflow.com/a/729725/233098 Praktycznie, ponieważ wiele narzędzi uniksowych wymaga lub oczekuje go do prawidłowego wyświetlania stackoverflow.com/a/729795/233098 . Filozoficznie, ponieważ każda linia w pliku tekstowym kończy się znakiem „końca linii” - ostatni wiersz nie powinien być wyjątkiem. Myśląc o tym inaczej, zbadajmy odwrotność. Jeśli zamiast „końca linii” byłby znacznik „początku linii”, czy pominąłbyś znak „linii początku” w pierwszej linii?
Joe
29
@Joe To nie ma większego sensu. Nowa linia to nowa linia , tzn. Separator między liniami, a nie koniec linii. Nie mamy znaków początku linii, ponieważ nie są one konieczne. Nie mamy znaków końca linii z tego samego powodu.
acjay
6
@acjay Twierdzę, że między „Separator między liniami” a „końcem linii” jest z natury lepsza. Żaden z tych poglądów nie jest z natury właściwy ani zły, tylko jeden sposób, aby na nie spojrzeć. Sugeruję, abyśmy nadal używali punktu widzenia, który jest praktyczny z historycznego punktu widzenia, ponieważ już to robimy w ten sposób i ma to sens, gdy się je akceptuje. Spójność jest ważna. Nie ma potrzeby przerywania tego w imię punktu widzenia „separator między liniami”.
Joe
17
@WORMSS „Nowość dla mnie” to nie to samo, co „nowa konwencja”. To tak, jakby odkryć jakąkolwiek inną konwencję programowania. Po prostu idź z tym. Państwo mogli odstąpić, ale jesteś tylko izolowanie siebie. (Lub w tym przypadku faktycznie łamiące narzędzia.) Zastanów się, ilu innych odkryło jakąś konwencję Railsów lub PEP8 i jak spójne były te społeczności jako całość, ponieważ się poddały - mimo że napisały kod przeciwnie.
Joe
100
To nie tylko zły styl, może prowadzić do nieoczekiwanego zachowania podczas korzystania z innych narzędzi w pliku.
Oto test.txt:
first line
second line
W ostatnim wierszu nie ma znaku nowej linii. Zobaczmy, ile wierszy znajduje się w pliku:
$ wc -l test.txt
1 test.txt
Może właśnie tego chcesz, ale w większości przypadków prawdopodobnie spodziewałbyś się, że w pliku będą 2 linie.
Ponadto, jeśli chcesz połączyć pliki, może nie działać w oczekiwany sposób:
$ cat test.txt test.txt
first line
second linefirst line
second line
Wreszcie, spowodowałoby to, że twoje różnice byłyby nieco głośniejsze, gdybyś dodał nową linię. Jeśli dodasz trzeci wiersz, wyświetli się edycja drugiego wiersza, a także nowy dodatek.
Wynik cat jest w porządku, ale parametr wc „-l, --lines” jest po prostu błędny. Nawet w podręczniku jest napisane: „drukuj liczby nowych linii”, a nie „drukuj liczby nowych linii”.
Niesamowity
I nie mogę nawet tego odtworzyć (wc i cat) z najnowszym util linux (util-linux 2.34).
wget
1
@wget Jestem na util-linux 2.34 i może potwierdzić, że to, co opisuje ta odpowiedź, to bieżące zachowanie. Domyślam się, że twój edytor dodał znak „\ n”.
stephanos
29
Jedynym powodem jest to, że w Uniksie historycznie istniała konwencja wszystkich czytelnych dla ludzi plików tekstowych kończących się nową linią. W tym czasie unikano dodatkowego przetwarzania podczas wyświetlania lub dołączania plików tekstowych i unikano traktowania plików tekstowych inaczej niż plików zawierających inne rodzaje danych (np. Surowe dane binarne, które nie są czytelne dla człowieka).
Z powodu tej konwencji wiele narzędzi z tamtej epoki oczekuje końca nowej linii, w tym edytory tekstu, narzędzia różnicowania i inne narzędzia do przetwarzania tekstu. Mac OS X został zbudowany na BSD Unix, a Linux został opracowany tak, aby był kompatybilny z Unixem, więc oba systemy operacyjne odziedziczyły tę samą konwencję, zachowanie i narzędzia.
System Windows nie został opracowany pod kątem zgodności z systemem Unix, więc nie ma tej samej konwencji, a większość oprogramowania Windows poradzi sobie dobrze bez końca nowej linii.
Ale odkąd Git został opracowany najpierw dla Linuksa, a wiele programów typu open source jest zbudowanych na systemach kompatybilnych z Unixem, takich jak Linux, Mac OS X, FreeBSD itp., Większość społeczności open source i ich narzędzia (w tym języki programowania) nadal trwają przestrzegać tych konwencji.
Istnieją powody techniczne, które miały sens w 1971 roku, ale w tej erze jest to głównie konwencja i utrzymanie zgodności z istniejącymi narzędziami.
Jeśli dodasz nową linię tekstu na końcu istniejącego pliku, który nie ma jeszcze newline characterna końcu, diff pokaże starą ostatnią linię jako zmodyfikowaną, nawet jeśli koncepcyjnie tak nie było.
Jest to co najmniej jeden dobry powód, aby dodać newline characterna końcu.
-}
\ No newline at end of file
+}
+// Useful comment.
Innymi słowy, pokazuje większą różnicę niż występowała koncepcyjnie. To pokazuje, że usunąłeś linię }i dodałeś ją }\n. W rzeczywistości tak się stało, ale nie jest to koncepcyjne , więc może być mylące.
Możemy napisać to samo w innym kierunku: jeśli usuniesz nową linię na końcu istniejącego pliku, który ma już nową linię na końcu, diff pokaże starą ostatnią linię również jako zmodyfikowaną, jeśli koncepcyjnie jej nie ma. Przynajmniej jeden dobry powód, aby usunąć nowy wiersz na końcu.
gentiane
3
@gentiane Mylą się „nowa linia” (nowa linia) i „nowa linia” (1 lub 2 znaki ograniczające koniec linii)
minexew
@minexew Nie, Gentiane nie jest. Może po prostu nie zdajesz sobie sprawy, że „nowa linia” jest taka sama jak „nowa linia”.
Niesamowity
3
@TheincredibleJan Sposób, w jaki są użyte w odpowiedzi, oba terminy mają odrębne znaczenie. Nie wiem, czy starasz się być mądrym dupkiem, czy po prostu źle rozumiesz, co się dzieje.
minexew
18
Wskazuje tylko, że koniec pliku nie ma nowej linii. To nie jest katastrofa, to tylko wiadomość, aby wyjaśnić, że nie ma żadnej, gdy patrzy się na różnicę w linii poleceń.
Powodem, dla którego ta konwencja weszła w życie, jest to, że w systemach operacyjnych typu UNIX znak nowej linii jest traktowany jako terminator linii i / lub granica komunikatów (obejmuje to przesyłanie potokowe między procesami, buforowanie linii itp.).
Rozważmy na przykład, że plik zawierający tylko znak nowej linii jest traktowany jako pojedynczy pusty wiersz. I odwrotnie, plik o długości zero bajtów jest w rzeczywistości pustym plikiem z zerowymi liniami. Można to potwierdzić zgodnie zwc -l poleceniem.
W sumie takie zachowanie jest uzasadnione, ponieważ nie byłoby innego sposobu rozróżnienia pustego pliku tekstowego od pliku tekstowego z pojedynczą pustą linią, gdyby \nznak był jedynie separatorem linii, a nie zakończeniem linii. Dlatego prawidłowe pliki tekstowe powinny zawsze kończyć się znakiem nowej linii. Jedynym wyjątkiem jest sytuacja, gdy plik tekstowy ma być pusty (bez wierszy).
Dlaczego jestem przegłosowany -2? Zwróciłem uwagę nie tylko na potwierdzenie innych odpowiedzi (tj. Standardowe narzędzia oparte na UNIX-u oczekują nowej linii jako terminatora linii), ale także na to, że nie ma sposobu na odróżnienie pustego pliku od pojedynczej pustej linii, co jest absolutną prawdą . Odpowiedziałem konkretnie na pierwotne pytanie „Jakie jest znaczenie wiadomości i co ona próbuje nam powiedzieć?”
Leslie Krause,
Nie głosowałem za tobą, ale ta odpowiedź wydaje się być specyficzna dla systemów typu Unix, ponieważ ma zastosowanie tylko wtedy, gdy nowa linia jest tylko znakiem nowej linii. Nie jest jasne, czy dotyczy to tutaj. Ostrzeżenie wydaje się również bezużyteczne, jeśli plik składa się z pustej linii. Unikam jednak Stackoverflow, ponieważ ludzie często głosują bez wyjaśnienia.
user34660
9
Jest jedna rzecz, której nie widzę w poprzednich odpowiedziach. Ostrzeżenie o braku końca linii może być ostrzeżeniem, gdy część pliku zostanie obcięta. Może to być objaw braku danych.
Dobra uwaga w ogóle, ale nie sądzę, aby miało to sens w kontekście tego konkretnego pytania.
cst1992
@ cst1992 Odpowiedzi w Stackoverflow powinny być jak najbardziej przydatne, co oznacza, że mają zastosowanie do wszystkich możliwości. Pytanie jest krótkie i nie widzę, gdzie wyklucza to możliwość, którą zasugerowałem.
user34660
7
Podstawowym problemem jest to, co definiujesz linię i czy sekwencja znaków end-on-line jest częścią linii, czy nie. Edytory oparte na UNIX (takie jak VIM) lub narzędzia (takie jak Git) używają sekwencji znaków EOL jako terminatora linii, dlatego jest to część linii. Jest podobny do używania średnika (;) w C i Pascalu. W C średnik kończy instrukcje, w Pascal oddziela je.
To faktycznie powoduje problem, ponieważ zakończenia linii są automatycznie modyfikowane, usuwając pliki bez wprowadzania w nich żadnych zmian. Zobacz ten post w celu rozwiązania.
Pliki źródłowe są często łączone przez narzędzia (C, C ++: pliki nagłówkowe, Javascript: programy pakujące). Jeśli pominiesz znak nowej linii, możesz wprowadzić nieprzyjemne błędy (gdzie ostatnia linia jednego źródła jest połączona z pierwszą linią następnego pliku źródłowego). Mam nadzieję, że wszystkie narzędzia konkatacji kodu źródłowego wstawiają nowy wiersz między połączonymi plikami, ale nie zawsze tak jest.
Sedno problemu polega na tym, że - w większości języków znaki nowej linii mają znaczenie semantyczne, a koniec pliku nie jest zdefiniowaną w języku alternatywą dla znaku nowej linii. Więc powinieneś zakończyć każde wyrażenie / wyrażenie znakiem nowej linii - łącznie z ostatnim.
W C / C ++ możesz napisać cały projekt w jednym wierszu. Nie ma potrzeby wprowadzania nowej linii.
Niesamowity
Ty mógł napisać cały swój projekt w jednej linii ... jeśli nie używać //komentarz styl w środku kodu.
Doug Coburn,
2
Twój oryginalny plik prawdopodobnie nie miał znaku nowej linii.
Jednak niektóre edytory, takie jak gedit w systemie Linux, po cichu dodają nową linię na końcu pliku. Nie możesz pozbyć się tej wiadomości podczas korzystania z tego rodzaju edytorów.
O ile warto, napotkałem to, gdy utworzyłem projekt IntelliJ na komputerze Mac, a następnie przeniosłem projekt na moją maszynę z systemem Windows. Musiałem ręcznie otworzyć każdy plik i zmienić ustawienie kodowania w prawym dolnym rogu okna IntelliJ. Prawdopodobnie nie zdarzyło się to większości, jeśli ktokolwiek czytał to pytanie, ale to mogło zaoszczędzić mi kilka godzin pracy ...
Odpowiedzi:
Wskazuje, że nie masz nowego wiersza (zwykle
'\n'
aka CR lub CRLF) na końcu pliku.To po prostu ostatni bajt (lub bajty w systemie Windows) w pliku nie jest znakiem nowej linii.
Komunikat jest wyświetlany, ponieważ w przeciwnym razie nie można odróżnić pliku, w którym na końcu znajduje się nowa linia, a gdzie nie ma. Diff i tak musi wypisać nowy wiersz, inaczej wynik będzie trudniejszy do odczytania lub przetworzenia automatycznie.
Zauważ, że dobrym stylem jest zawsze umieszczanie nowego wiersza jako ostatniego znaku, jeśli pozwala na to format pliku. Ponadto, na przykład, w przypadku plików nagłówkowych C i C ++ jest to wymagane przez standard językowy.
źródło
To nie tylko zły styl, może prowadzić do nieoczekiwanego zachowania podczas korzystania z innych narzędzi w pliku.
Oto
test.txt
:W ostatnim wierszu nie ma znaku nowej linii. Zobaczmy, ile wierszy znajduje się w pliku:
Może właśnie tego chcesz, ale w większości przypadków prawdopodobnie spodziewałbyś się, że w pliku będą 2 linie.
Ponadto, jeśli chcesz połączyć pliki, może nie działać w oczekiwany sposób:
Wreszcie, spowodowałoby to, że twoje różnice byłyby nieco głośniejsze, gdybyś dodał nową linię. Jeśli dodasz trzeci wiersz, wyświetli się edycja drugiego wiersza, a także nowy dodatek.
źródło
Jedynym powodem jest to, że w Uniksie historycznie istniała konwencja wszystkich czytelnych dla ludzi plików tekstowych kończących się nową linią. W tym czasie unikano dodatkowego przetwarzania podczas wyświetlania lub dołączania plików tekstowych i unikano traktowania plików tekstowych inaczej niż plików zawierających inne rodzaje danych (np. Surowe dane binarne, które nie są czytelne dla człowieka).
Z powodu tej konwencji wiele narzędzi z tamtej epoki oczekuje końca nowej linii, w tym edytory tekstu, narzędzia różnicowania i inne narzędzia do przetwarzania tekstu. Mac OS X został zbudowany na BSD Unix, a Linux został opracowany tak, aby był kompatybilny z Unixem, więc oba systemy operacyjne odziedziczyły tę samą konwencję, zachowanie i narzędzia.
System Windows nie został opracowany pod kątem zgodności z systemem Unix, więc nie ma tej samej konwencji, a większość oprogramowania Windows poradzi sobie dobrze bez końca nowej linii.
Ale odkąd Git został opracowany najpierw dla Linuksa, a wiele programów typu open source jest zbudowanych na systemach kompatybilnych z Unixem, takich jak Linux, Mac OS X, FreeBSD itp., Większość społeczności open source i ich narzędzia (w tym języki programowania) nadal trwają przestrzegać tych konwencji.
Istnieją powody techniczne, które miały sens w 1971 roku, ale w tej erze jest to głównie konwencja i utrzymanie zgodności z istniejącymi narzędziami.
źródło
Jeśli dodasz nową linię tekstu na końcu istniejącego pliku, który nie ma jeszcze
newline character
na końcu, diff pokaże starą ostatnią linię jako zmodyfikowaną, nawet jeśli koncepcyjnie tak nie było.Jest to co najmniej jeden dobry powód, aby dodać
newline character
na końcu.Przykład
Plik zawiera:
Hexdump:
Teraz go edytujesz
Hexdump:
Git diff pokaże:
Innymi słowy, pokazuje większą różnicę niż występowała koncepcyjnie. To pokazuje, że usunąłeś linię
}
i dodałeś ją}\n
. W rzeczywistości tak się stało, ale nie jest to koncepcyjne , więc może być mylące.źródło
Wskazuje tylko, że koniec pliku nie ma nowej linii. To nie jest katastrofa, to tylko wiadomość, aby wyjaśnić, że nie ma żadnej, gdy patrzy się na różnicę w linii poleceń.
źródło
Powodem, dla którego ta konwencja weszła w życie, jest to, że w systemach operacyjnych typu UNIX znak nowej linii jest traktowany jako terminator linii i / lub granica komunikatów (obejmuje to przesyłanie potokowe między procesami, buforowanie linii itp.).
Rozważmy na przykład, że plik zawierający tylko znak nowej linii jest traktowany jako pojedynczy pusty wiersz. I odwrotnie, plik o długości zero bajtów jest w rzeczywistości pustym plikiem z zerowymi liniami. Można to potwierdzić zgodnie z
wc -l
poleceniem.W sumie takie zachowanie jest uzasadnione, ponieważ nie byłoby innego sposobu rozróżnienia pustego pliku tekstowego od pliku tekstowego z pojedynczą pustą linią, gdyby
\n
znak był jedynie separatorem linii, a nie zakończeniem linii. Dlatego prawidłowe pliki tekstowe powinny zawsze kończyć się znakiem nowej linii. Jedynym wyjątkiem jest sytuacja, gdy plik tekstowy ma być pusty (bez wierszy).źródło
Jest jedna rzecz, której nie widzę w poprzednich odpowiedziach. Ostrzeżenie o braku końca linii może być ostrzeżeniem, gdy część pliku zostanie obcięta. Może to być objaw braku danych.
źródło
Podstawowym problemem jest to, co definiujesz linię i czy sekwencja znaków end-on-line jest częścią linii, czy nie. Edytory oparte na UNIX (takie jak VIM) lub narzędzia (takie jak Git) używają sekwencji znaków EOL jako terminatora linii, dlatego jest to część linii. Jest podobny do używania średnika (;) w C i Pascalu. W C średnik kończy instrukcje, w Pascal oddziela je.
źródło
To faktycznie powoduje problem, ponieważ zakończenia linii są automatycznie modyfikowane, usuwając pliki bez wprowadzania w nich żadnych zmian. Zobacz ten post w celu rozwiązania.
git zastępuje LF przez CRLF
źródło
Pliki źródłowe są często łączone przez narzędzia (C, C ++: pliki nagłówkowe, Javascript: programy pakujące). Jeśli pominiesz znak nowej linii, możesz wprowadzić nieprzyjemne błędy (gdzie ostatnia linia jednego źródła jest połączona z pierwszą linią następnego pliku źródłowego). Mam nadzieję, że wszystkie narzędzia konkatacji kodu źródłowego wstawiają nowy wiersz między połączonymi plikami, ale nie zawsze tak jest.
Sedno problemu polega na tym, że - w większości języków znaki nowej linii mają znaczenie semantyczne, a koniec pliku nie jest zdefiniowaną w języku alternatywą dla znaku nowej linii. Więc powinieneś zakończyć każde wyrażenie / wyrażenie znakiem nowej linii - łącznie z ostatnim.
źródło
//
komentarz styl w środku kodu.Twój oryginalny plik prawdopodobnie nie miał znaku nowej linii.
Jednak niektóre edytory, takie jak gedit w systemie Linux, po cichu dodają nową linię na końcu pliku. Nie możesz pozbyć się tej wiadomości podczas korzystania z tego rodzaju edytorów.
Próbowałem przezwyciężyć ten problem, aby otworzyć plik za pomocą edytora kodu Visual Studio
Ten edytor wyraźnie pokazuje ostatni wiersz i możesz go usunąć, jak chcesz.
źródło
O ile warto, napotkałem to, gdy utworzyłem projekt IntelliJ na komputerze Mac, a następnie przeniosłem projekt na moją maszynę z systemem Windows. Musiałem ręcznie otworzyć każdy plik i zmienić ustawienie kodowania w prawym dolnym rogu okna IntelliJ. Prawdopodobnie nie zdarzyło się to większości, jeśli ktokolwiek czytał to pytanie, ale to mogło zaoszczędzić mi kilka godzin pracy ...
źródło