Niektóre kompilatory (zwłaszcza C lub C ++) ostrzegają o:
No new line at end of file
Myślałem, że będzie to problem tylko dla programistów C, ale github wyświetla komunikat w widoku zatwierdzania:
\ No newline at end of file
dla pliku PHP.
Rozumiem proces preprocesora wyjaśniony w tym wątku , ale co to ma wspólnego z PHP? Czy to to samo include()
, czy jest związane z tematem \r\n
vs \n
?
Po co mieć nową linię na końcu pliku?
cat
plik, następny monit zostanie dodany do ostatniej „linii”, jeśli nie kończy się na nowej linii.Odpowiedzi:
Tu nie chodzi o dodanie nowej linii na końcu pliku, nie chodzi o usunięcie nowej linii, która powinna tam być.
Plik tekstowy , pod Uniksem, składa się z szeregu linii , z których każda kończy się znakiem nowej linii (
\n
). Plik, który nie jest pusty i nie kończy się na nowej linii, nie jest zatem plikiem tekstowym.Narzędzia, które powinny działać na plikach tekstowych, mogą nie radzić sobie dobrze z plikami, które nie kończą się znakiem nowej linii; historyczne narzędzia uniksowe mogą na przykład ignorować tekst po ostatniej nowej linii. Programy narzędziowe GNU zachowują się przyzwoicie w przypadku plików nietekstowych, podobnie jak większość innych nowoczesnych programów narzędziowych, ale nadal możesz napotkać dziwne zachowanie w przypadku plików, które nie mają ostatniej nowej linii¹.
W przypadku GNU diff, jeśli jeden z porównywanych plików kończy się znakiem nowej linii, ale nie drugim, należy to zauważyć. Ponieważ diff jest zorientowany liniowo, nie może tego wskazać, przechowując nową linię dla jednego z plików, ale nie dla innych - nowe linie są konieczne do wskazania, gdzie każda linia w pliku diff zaczyna się i kończy. Tak więc diff używa tego specjalnego tekstu
\ No newline at end of file
do odróżnienia pliku, który nie kończył się nową linią od pliku, który tak zrobił.Nawiasem mówiąc, w kontekście C plik źródłowy podobnie składa się z szeregu linii. Mówiąc dokładniej, jednostka tłumacząca jest postrzegana w implementacji zdefiniowanej jako seria wierszy, z których każda musi kończyć się znakiem nowej linii ( n1256 §5.1.1.1). W systemach uniksowych mapowanie jest proste. W systemach DOS i Windows każda sekwencja CR LF (
\r\n
) jest odwzorowana na nową linię (\n
; to zawsze dzieje się podczas odczytu pliku otwartego jako tekst w tych systemach operacyjnych). Istnieje kilka systemów operacyjnych, które nie mają znaku nowej linii, ale zamiast tego mają rekordy o stałej lub zmiennej wielkości; w tych systemach mapowanie plików do źródła C wprowadza\n
na końcu każdego rekordu. Chociaż nie ma to bezpośredniego związku z Uniksem, oznacza to, że jeśli skopiujesz plik źródłowy C, w którym brakuje jego ostatniej nowej linii, do systemu z plikami tekstowymi opartymi na rekordach, a następnie skopiujesz go z powrotem, albo skończysz z niekompletnym ostatnia linia została obcięta w początkowej konwersji lub dodatkowa nowa linia przyczepiona do niej podczas konwersji do tyłu.¹ Przykład: wynik sortowania GNU zawsze kończy się nową linią. Więc jeśli w pliku
foo
brakuje ostatniego nowego wiersza, zauważysz, żesort foo | wc -c
zgłasza on o jeden znak więcej niżcat foo | wc -c
.źródło
Niekoniecznie przyczyna, ale praktyczna konsekwencja plików, które nie kończą się na nowej linii:
Zastanów się, co by się stało, gdybyś chciał przetworzyć kilka plików przy użyciu
cat
. Na przykład, jeśli chcesz znaleźć słowofoo
na początku wiersza w 3 plikach:Jeśli pierwsza linia w pliku3 zaczyna się od
foo
, ale plik2 nie ma końca\n
po ostatniej linii, to wystąpienie nie zostanie znalezione przez grep, ponieważ ostatnia linia w pliku2 i pierwsza linia w pliku3 byłyby widoczne przez grep jako pojedynczy linia.Aby zachować spójność i uniknąć niespodzianek, staram się, aby moje pliki zawsze kończyły się nową linią.
źródło
'\n'
w operacji kota ...\n
znaków, które mają białe znaki lub białe znaki, więc aby zachować spójność, zawsze umieszczam\n _____
oba końce moich łańcuchów”. Cóż, nie, właściwą rzeczą do zrobienia jest przycięcie Strun, a następnie ich prawidłowe połączenie.Istnieją dwa aspekty:
Istnieją / były niektóre kompilatory C, które nie mogą przeanalizować ostatniego wiersza, jeśli nie kończy się on nowym wierszem. Standard C określa, że plik C powinien kończyć się nową linią (C11, 5.1.1.2, 2.) i że ostatni wiersz bez nowej linii daje niezdefiniowane zachowanie (C11, J.2, 2. pozycja). Być może z przyczyn historycznych, ponieważ jakiś sprzedawca takiego kompilatora był częścią komitetu, kiedy napisano pierwszy standard. Zatem ostrzeżenie GCC.
diff
programy (takie jak używane przezgit diff
github itp.) pokazują różnice między wierszami między plikami. Zwykle drukują komunikat, gdy tylko jeden plik kończy się znakiem nowej linii, ponieważ inaczej nie zobaczyłbyś tej różnicy. Na przykład, jeśli jedyną różnicą między dwoma plikami jest obecność ostatniego znaku nowej linii, bez podpowiedzi wyglądałoby to tak, jakby oba pliki były takie same, kiedydiff
icmp
zwracają kod wyjścia niejednakowy sukces i sumy kontrolne plików (np. Przezmd5sum
) nie pasują.źródło
diff
oczekuje się, że wydrukuje różnice, jeśli takie istnieją. A jeśli jeden plik ma nowy wiersz jako ostatni znak, podczas gdy drugi go nie ma, to różnica musi być jakoś zauważalna w wyniku.\n
), może po prostu pokazywać „nowe linie”.Otrzymane
\ No newline at end of file
z github pojawia się na końcu łatki (wdiff
formacie , patrz uwaga na końcu sekcji „Unified Format”).Kompilatory nie dbają o to, czy na końcu pliku jest nowa linia, czy nie, ale
git
(idiff
/patch
utilities) muszą wziąć to pod uwagę. Jest wiele powodów. Na przykład zapomnienie o dodaniu lub usunięciu nowego wiersza na końcu pliku zmieniłoby jego skrót (md5sum
/sha1sum
). Ponadto pliki nie zawsze są programami, a finał\n
może coś zmienić.Uwaga : Jeśli chodzi o ostrzeżenie z kompilatorów C, myślę, że nalegają na końcową nową linię dla celów zgodności wstecznej. Bardzo stare kompilatory mogą nie zaakceptować ostatniego wiersza, jeśli się nie kończą
\n
(lub inną zależną od systemu sekwencją znakową końca wiersza).źródło
POSIX, jest to zestaw standardów określonych przez IEEE w celu utrzymania zgodności między systemami operacyjnymi.
Jednym z nich jest definicja „linii”, która jest ciągiem zerowym lub większą liczbą znaków niebędących znakami oraz kończącym znakiem nowej linii.
Aby ostatnia linia została rozpoznana jako rzeczywista „linia”, powinna ona mieć znak kończący nowy wiersz.
Jest to ważne, jeśli polegasz na narzędziach systemu operacyjnego, aby powiedzieć liczbę wierszy lub podzielić / pomóc przeanalizować plik. Biorąc pod uwagę, że PHP jest językiem skryptowym, jest całkowicie możliwe, szczególnie w jego początkowych dniach lub nawet teraz (nie mam pojęcia / postuluje), że miał takie zależności OS.
W rzeczywistości większość systemów operacyjnych nie jest w pełni zgodna z POSIX, a ludzie nie są tacy jak maszyny, a nawet nie dbają o zakończenie nowych linii. Więc dla większości rzeczy jest to smorgasbord wszystkiego, co się o to troszczy, ostrzega lub po prostu idzie, że ostatnia część tekstu jest naprawdę wierszem, więc po prostu to dołącz.
źródło
Warto również zachować historię różnic. Jeśli plik kończy się bez znaku nowej linii, to dodawanie czegokolwiek na końcu pliku będzie postrzegane przez narzędzia różnicujące jako zmiana tego ostatniego wiersza (ponieważ
\n
jest do niego dodawany).Może to powodować niepożądane wyniki za pomocą poleceń takich jak
git blame
ihg annotate
.źródło