파일 끝에 새 줄을 추가하면 어떤 점이 좋습니까?


166

일부 컴파일러 (특히 C 또는 C ++ 컴파일러)는 다음에 대한 경고를 표시합니다.

No new line at end of file

나는 이것이 C 프로그래머 전용 문제라고 생각했지만 github은 커밋보기에 메시지를 표시합니다.

\ No newline at end of file

PHP 파일.

이 스레드 에서 설명한 전 처리기 문제를 이해 하지만 PHP와 관련이 있습니까? 그것은 같은 include()것 입니까 아니면 \r\nvs \n주제 와 관련이 있습니까?

파일 끝에 줄 바꿈이 필요한 이유는 무엇입니까?



2
사람들을 화나게합니다.
앤드류

3
당신이 경우 cat이 줄 바꿈으로 끝나지 않는 경우 파일, 다음 메시지가 마지막 "라인"에 추가됩니다.
Aaron Franke

답변:


185

파일 끝에 줄 바꿈을 추가하는 것이 아니라 거기에 있어야하는 줄 바꿈을 제거하지 않는 것입니다.

텍스트 파일 , 유닉스에서의 일련의 구성 라인 로 끝나는, 각각의 개행 문자 ( \n). 비어 있지 않고 개행 문자로 끝나지 않는 파일은 텍스트 파일이 아닙니다.

텍스트 파일에서 작동해야하는 유틸리티는 줄 바꿈으로 끝나지 않는 파일에는 잘 맞지 않을 수 있습니다. 예를 들어 역사적 유닉스 유틸리티는 마지막 개행 이후의 텍스트를 무시할 수 있습니다. GNU 유틸리티는 텍스트가 아닌 파일과 함께 동작하는 정책을 가지고 있으며, 대부분의 다른 최신 유틸리티도 마찬가지입니다. 그러나 최종 줄 바꿈이없는 파일에는 여전히 이상한 동작이 발생할 수 있습니다 ¹.

GNU diff를 사용하면 비교할 파일 중 하나가 줄 바꿈으로 끝나고 다른 줄은 끝나지 않으면주의해야합니다. diff는 행 지향적이므로 파일 중 하나의 줄 바꿈을 저장하여 다른 줄이 아닌 줄 바꿈을 저장하여이를 나타낼 수는 없습니다 . diff 파일의 각 줄 시작하고 끝나는 위치를 나타내는 데 줄 바꿈이 필요합니다 . 따라서 diff는이 특수 텍스트 \ No newline at end of file를 사용 하여 줄 바꿈으로 끝나지 않은 파일을 수행 한 파일과 구별합니다.

그건 그렇고, C 컨텍스트에서 소스 파일은 유사하게 일련의 라인으로 구성됩니다. 더 정확하게 말하면, 번역 단위는 구현 정의에서 일련의 행으로 볼 수 있으며 각 행은 개행 문자 ( n1256 §5.1.1.1)로 끝나야합니다. 유닉스 시스템에서는 매핑이 간단합니다. DOS 및 Windows에서 각 CR LF 시퀀스 ( \r\n)는 줄 바꿈에 매핑됩니다 ( \n;이 OS에서 텍스트로 열린 파일을 읽을 때 항상 발생 함). 개행 문자가 없지만 고정 또는 가변 크기의 레코드가있는 몇 가지 OS가 있습니다. 이러한 시스템에서 파일에서 C 소스로의 맵핑은\n각 레코드의 끝에서. 이것은 유닉스와 직접 관련이 없지만 마지막 줄 바꿈이없는 C 소스 파일을 레코드 기반 텍스트 파일이있는 시스템에 복사 한 다음 다시 복사하면 불완전하게 끝날 것입니다 초기 변환에서 마지막 줄이 잘 리거나 역 변환 중에 줄 바꿈이 추가되었습니다.

¹ 예 : GNU 정렬의 출력은 항상 줄 바꿈으로 끝납니다. 따라서 파일 foo에 마지막 줄 바꿈이 없으면 . sort foo | wc -c보다 문자가 하나 더보고 cat foo | wc -c됩니다.


"... 일련의 행은 각각 개행 문자 (n1256 §5.1.1.1)로 끝나야합니다."-> 최신 C11dr N1570을 다시 살펴보면 다음과 같은 것 이외의 지원은 찾지 못했습니다. "비어 있지 않은 소스 파일은 개행 문자로 끝나야하며, 그러한 스 플라이 싱이 발생하기 전에 백 슬래시 문자가 바로 앞에 오지 않아야합니다." §5.1.1.2 2, 그러나 이것은 스 플라이 싱 사양으로 제한되는 것 같습니다.
chux

@chux 그 문장은 n1256에도 있습니다. 마지막 줄은 개행 문자로 끝나야합니다. 마지막 줄이 아닌 줄은 분명히 줄 바꿈 문자로 끝나야 그 줄이 끝나고 다음 줄이 시작됨을 나타냅니다. 따라서 모든 줄은 개행 문자로 끝나야합니다.
Gilles

흠, 저에게 ""소스 파일 ... 스 플라이 싱이 발생합니다. "라는 줄은 일반적으로 파일이 아닌 스 플라이 싱 고려 사항으로 제한 될 수 있습니다. 그는에 초점을 맞추고 있습니다.
chux

""따라서 diff는 파일 끝에 줄 바꿈이없는 특수 파일을 사용하여 줄 바꿈으로 끝나지 않은 파일을 파일과 구분합니다. " 힘내는 파일을 비교할 때뿐만 아니라이 텍스트를 보여줍니다. 그러나 새 파일이 git에 추가 된 경우에도 마찬가지입니다. 따라서이 주장은 유효하지 않습니다.
Viktor Kruglikov

> "텍스트 파일에서 작동하는 유틸리티는 줄 바꿈으로 끝나지 않는 파일에는 잘 맞지 않을 수 있습니다"POSIX 때문에 \ n 누락과 같은 낮은 수준의 문제에 관심을 갖는 것은 git의 사업이라고 생각하지 않습니다. 요구 사항. git 이이 메시지를 표시하면 이유는 소스 제어 문제 에 있어야한다고 생각합니다 .
Viktor Kruglikov

41

반드시 그 이유는 아니지만 파일이 새로운 줄로 끝나지 않는 실제적인 결과는 다음과 같습니다.

를 사용하여 여러 파일을 처리하려면 어떻게되는지 고려하십시오 cat. 예를 들어, foo3 개의 파일에서 행의 시작 부분에서 단어를 찾으려면 다음을 수행하십시오.

cat file1 file2 file3 | grep -e '^foo'

file3의 첫 번째 행이로 시작 foo하지만 file2에 \n마지막 행 다음에 마지막이없는 경우, grep에서는 file2의 마지막 행과 file3의 첫 번째 행을 단일로 표시하므로 grep에서이 발생을 찾을 수 없습니다. 선.

따라서 일관성을 유지하고 놀라움을 피하기 위해 파일을 항상 새 줄로 끝내려고합니다.


그러나 파일 연결을 걱정하는 것이 git의 사업입니까?
Viktor Kruglikov

당신은 '\n'고양이 수술에 넣어야하는 이유가 아닙니다 ...
앤드류

3
"때로는 \n끝에 공백 이 있거나 공백 이있는 문자열을 함께 추가 하기 때문에 일관성을 유지하기 위해 항상 \n _____문자열의 양쪽 끝에 놓습니다 ." 글쎄, 아니, 옳은 일은 문자열을 다듬은 다음 올바르게 연결하는 것입니다.
앤드류

16

두 가지 측면이 있습니다.

  1. 줄 바꿈으로 끝나지 않으면 마지막 줄을 구문 분석 할 수없는 일부 C 컴파일러가 있습니다. C 표준은 C 파일이 개행 (C11, 5.1.1.2, 2)으로 끝나고 개행이없는 마지막 행은 정의되지 않은 동작 (C11, J.2, 2 번째 항목)을 생성하도록 지정합니다. 역사적인 이유는 아마도 그러한 컴파일러의 일부 공급 업체가 첫 번째 표준이 작성되었을 때위원회의 일부 였기 때문일 것입니다. 따라서 GCC에 의한 경고.

  2. diff프로그램 ( git diff, github 등에서 사용되는 것과 같이 )은 파일 간의 줄 단위 차이를 보여줍니다. 일반적으로 한 파일 만 줄 바꿈으로 끝나는 경우 메시지를 인쇄합니다. 그렇지 않으면이 차이가 표시되지 않습니다. 동일 하였다 때 두 파일 사이의 유일한 차이는 두 파일과 같을 것이다 힌트없이, 마지막 개행 문자의 존재 인 경우 예를 들어, diffcmp(종료 코드 불평등 성공과 파일의 체크섬을 반환 예를 통해 md5sum)이 일치하지 않습니다.


diff 프로그램으로 이해하십시오
Thamaraiselvam

diffs 같은 소리는 더 똑똑해야합니다.
앤드류

@ 앤드류, 아니, 그렇지 않습니다. diff차이가 있으면 인쇄 할 것으로 예상됩니다. 그리고 한 파일에 마지막 문자로 줄 바꿈이 있고 다른 파일에는 줄 바꿈이 없으면 출력에서 ​​그 차이가 눈에 띄어 야합니다.
maxschlepzig

후자의 진술이 정확합니다. 그러나 diff 뷰어는 "줄 바꾸기"( \n)를 표시 할 필요가 없으며 단순히 "줄 바꾸기"를 표시 할 수 있습니다.
앤드류

10

\ No newline at end of file당신이에서 얻을 github에이 패치의 끝에 나타납니다 (의 diff형식 은 "통합 형식"섹션의 마지막 부분의 설명을 참조).

컴파일러는 파일 끝에 줄 바꿈이 있는지 여부에 신경 쓰지 않지만 git(및 diff/ patch유틸리티)는 고려해야합니다. 그 이유는 여러 가지가 있습니다. 예를 들어, 파일 끝에 줄 바꿈을 추가하거나 제거하지 않으면 해시 섬 ( md5sum/ sha1sum) 이 변경 됩니다. 또한 파일이 항상 프로그램 인 것은 아니며 최종적으로 \n약간의 차이가있을 수 있습니다.

참고 : C 컴파일러의 경고에 대해서는 이전 버전과의 호환성을 위해 최종 개행이 필요하다고 생각합니다. 매우 오래된 컴파일러는 \n(또는 다른 시스템 종속 행 끝 문자 시퀀스)로 끝나지 않으면 마지막 행을 허용하지 않을 수 있습니다.


7
"이전 버전과의 호환성을 위해 최종 개행을 요구한다고 생각합니다." -아니, C 표준이이를 요구 하기 때문에 주장 합니다.
MestreLion

1
@MestreLion C에는 C 소스 코드 (C11 §5.1.1.2 2)에 대한 최종 개행이 필요합니다. 참고를위한 텍스트 파일 I / O, C는 "마지막 줄 구현을 정의하는 종료 개행 문자를 필요로하는지."가 §7.21.2 2
chux

누가 오래된 컴파일러를 사용하고 있습니까? 사용을 중지하십시오.
앤드류

1
@MestreLion : 그리고 왜 C 표준이 그것을 요구한다고 생각하십니까?
Stéphane Gimenez

@ StéphaneGimenez : 다양한 OS 간의 일관성, 더 나은 호환성 및 상호 운용성 (POSIX는 '\ n'으로 끝나는 줄도 정의)
MestreLion

4

POSIX, 이것은 운영 체제 간의 호환성을 유지하기 위해 IEEE에서 지정한 표준 세트입니다.

그 중 하나는 "줄"의 정의는 0 개 이상의 문자가 아닌 일련의 문자와 종료하는 개행 문자입니다.

따라서 마지막 줄이 실제 "줄"로 인식 되려면 새 줄 문자로 끝나야합니다.

OS 도구를 사용하여 줄 수 또는 파일 분할 / 도움말을 말하는 경우에 중요합니다. PHP는 스크립트 언어라고 할 수 있는데, 특히 초기 나 심지어 지금도 가능합니다.

실제로 대부분의 운영 체제는 POSIX를 완벽하게 준수하지 않으며 인간은 새로운 회선을 종료하는 것을 좋아하거나 신경 쓰지 않습니다. 따라서 대부분의 경우, 그것에 관심을 갖거나 경고하거나 마지막 텍스트를 보내는 것의 모든 것의 일부는 실제로 한 줄이므로 포함하십시오.


3

차이점 기록을 유지하는 요지도 있습니다. 줄 바꿈 문자없이 파일이 끝나면 파일 끝에 추가하면 마지막 줄을 변경하는 것으로 diff 유틸리티에서 볼 수 있습니다 ( \n추가 되었기 때문에 ).

이 같은 명령으로 원치 않는 결과가 발생할 수 git blamehg annotate.


diffs 같은 소리는 더 똑똑해야합니다.
앤드류
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.