ไม่มีการขึ้นบรรทัดใหม่ท้ายไฟล์


472

เมื่อทำgit diffมันบอกว่า"ไม่มีการขึ้นบรรทัดใหม่ที่จุดสิ้นสุดของไฟล์" "ไม่มีการขึ้นบรรทัดใหม่ในตอนท้ายของไฟล์"

ตกลงไม่มีบรรทัดใหม่ที่ท้ายไฟล์ เรื่องใหญ่อะไร

ข้อความสำคัญอะไรและมันพยายามบอกอะไรเรา


11
บางทีถ้าคุณมีไฟล์ที่ลงท้ายด้วยไม่มีการขึ้นบรรทัดใหม่และคุณเพิ่มบรรทัดอื่น git จะต้องแสดงว่าบรรทัดสุดท้ายก่อนมีการเปลี่ยนแปลงเนื่องจากมีอักขระขึ้นบรรทัดใหม่เป็นส่วนหนึ่งของบรรทัดหรือไม่
nafg

คำตอบ:


458

บ่งชี้ว่าคุณไม่มีบรรทัดใหม่ (ปกติ'\n'คือ CR หรือ CRLF) ที่ท้ายไฟล์

นั่นคือเพียงพูดไบต์สุดท้าย (หรือไบต์ถ้าคุณใช้ Windows) ในไฟล์ไม่ใช่บรรทัดใหม่

ข้อความจะปรากฏขึ้นเพราะมิฉะนั้นจะไม่มีวิธีที่จะบอกความแตกต่างระหว่างไฟล์ที่มีการขึ้นบรรทัดใหม่ในตอนท้ายและอีกหนึ่งที่ไม่มี Diff จะต้องแสดงบรรทัดใหม่หรือผลลัพธ์จะยากต่อการอ่านหรือประมวลผลโดยอัตโนมัติ

โปรดทราบว่ามันเป็นสไตล์ที่ดีที่จะวางบรรทัดใหม่เป็นอักขระตัวสุดท้ายหากได้รับอนุญาตจากรูปแบบไฟล์ นอกจากนี้ตัวอย่างเช่นสำหรับไฟล์ส่วนหัว C และ C ++ จำเป็นสำหรับมาตรฐานภาษา


136
คุณอยากอธิบายได้ไหมว่าเพราะเหตุใดจึงถือว่าเป็นสไตล์ที่ดีในการเพิ่มบรรทัดใหม่ให้เป็นอักขระตัวสุดท้ายเสมอ แก้ไข: พบการสนทนานี้
พอล Bellora

84
@PaulBellora ในอดีตก็คือการตัดสินใจที่ทำโดยมาตรฐาน C ภาษาstackoverflow.com/a/729725/233098จวนเพราะเครื่องมือที่ใช้ระบบปฏิบัติการยูนิกซ์ส่วนใหญ่ต้องการหรือคาดหวังสำหรับการแสดงผลที่เหมาะสมstackoverflow.com/a/729795/233098 ในเชิงปรัชญาเนื่องจากแต่ละบรรทัดในไฟล์ข้อความจะสิ้นสุดด้วยอักขระ "end-of-line" บรรทัดสุดท้ายไม่ควรมีข้อยกเว้นใด ๆ ลองคิดดูต่างออกไปก่อน หากมีเครื่องหมาย "start-of-line" แทน "end-of-line" คุณจะละเว้นอักขระ "start-of-line" ในบรรทัดแรกหรือไม่
โจ

29
@ โจนั่นไม่สมเหตุสมผลเลย ขึ้นบรรทัดใหม่คือบรรทัดใหม่กล่าวคือตัวคั่นระหว่างบรรทัดไม่ใช่จุดสิ้นสุดของบรรทัด เราไม่มีตัวอักษรเริ่มต้นเพราะไม่จำเป็น เราไม่มีตัวอักษรท้ายบรรทัดด้วยเหตุผลเดียวกัน
acjay

6
@ acjay ฉันให้เหตุผลว่ามี "ตัวคั่นระหว่างบรรทัด" และ "จุดสิ้นสุดของบรรทัด" ที่ดีกว่า ไม่ว่าจะเป็นมุมมองที่ถูกหรือผิดเพียงวิธีเดียวที่จะมองมัน ฉันบอกเรายังคงใช้มุมมองจุดที่ปฏิบัติในอดีตตั้งแต่ที่เรากำลังทำอยู่แล้วมันเป็นอย่างนั้นและมันก็ไม่ทำให้ความรู้สึกเมื่อคุณยอมรับมัน ความมั่นคงเป็นสิ่งสำคัญ ไม่จำเป็นต้องแยกสิ่งนั้นในชื่อของมุมมอง "ตัวคั่นระหว่างบรรทัด"
โจ

17
@WORMSS "ใหม่สำหรับฉัน" ไม่เหมือนกับ "แบบแผนใหม่" นี่เหมือนกับการค้นพบระเบียบวิธีการเขียนโปรแกรมอื่น ๆ คุณไปกับมัน คุณสามารถเบี่ยงเบนได้ แต่คุณแยกตัวเองเท่านั้น (หรือในกรณีนี้คือเครื่องมือทำลายจริง ๆ ) ลองคิดดูว่ามีคนอื่นอีกกี่คนที่ค้นพบการประชุม Rails หรือ PEP8 และชุมชนเหล่านั้นยังคงมีความสอดคล้องกันอย่างไรเพราะพวกเขาให้มา
Joe

100

มันไม่ใช่แค่สไตล์ที่ไม่ดีมันสามารถนำไปสู่พฤติกรรมที่ไม่คาดคิดเมื่อใช้เครื่องมืออื่น ๆ ในไฟล์

นี่คือtest.txt:

first line
second line

ไม่มีอักขระขึ้นบรรทัดใหม่ในบรรทัดสุดท้าย มาดูกันว่ามีไฟล์อยู่กี่ไฟล์:

$ wc -l test.txt
1 test.txt

อาจเป็นสิ่งที่คุณต้องการ แต่ในกรณีส่วนใหญ่คุณอาจคาดหวังว่าจะมี 2 บรรทัดในไฟล์

นอกจากนี้หากคุณต้องการรวมไฟล์มันอาจไม่ทำงานตามที่คุณคาดหวัง:

$ cat test.txt test.txt
first line
second linefirst line
second line

ในที่สุดมันจะทำให้เสียงรบกวนของคุณเพิ่มขึ้นเล็กน้อยหากคุณต้องการเพิ่มบรรทัดใหม่ หากคุณเพิ่มบรรทัดที่สามมันจะแสดงการแก้ไขในบรรทัดที่สองเช่นเดียวกับการเพิ่มใหม่


4
ผลลัพธ์ของ cat นั้นโอเค แต่พารามิเตอร์ wc "-l, --lines" นั้นผิดปกติ แม้ว่าจะเป็นคู่มือบอกว่า "พิมพ์จำนวนบรรทัดใหม่" และไม่ใช่ "พิมพ์จำนวนบรรทัด"
ไม่น่าเชื่อ

และฉันไม่สามารถทำซ้ำ (wc และ cat) ด้วย util linux ล่าสุด (util-linux 2.34)
wget

1
@wget ฉันใช้ util-linux 2.34 และสามารถยืนยันได้ว่าสิ่งที่คำตอบนี้อธิบายคือพฤติกรรมปัจจุบัน ฉันเดาว่าตัวแก้ไขของคุณเพิ่มอักขระ "\ n"
เตฟาโน

29

เหตุผลเดียวก็คือว่า Unix ในอดีตมีการประชุมของไฟล์ข้อความที่มนุษย์อ่านได้ทั้งหมดซึ่งลงท้ายด้วยบรรทัดใหม่ ในขณะนี้หลีกเลี่ยงการประมวลผลพิเศษเมื่อแสดงหรือเข้าร่วมไฟล์ข้อความและหลีกเลี่ยงการจัดการไฟล์ข้อความที่แตกต่างจากไฟล์ที่มีข้อมูลประเภทอื่น (เช่นข้อมูลไบนารีดิบซึ่งไม่สามารถอ่านได้โดยมนุษย์)

เนื่องจากการประชุมนี้เครื่องมือมากมายจากยุคนั้นจึงคาดหวังว่าจะมีการขึ้นบรรทัดใหม่ซึ่งรวมถึงเครื่องมือแก้ไขข้อความเครื่องมือที่ต่างกันและเครื่องมือประมวลผลข้อความอื่น ๆ Mac OS X สร้างขึ้นบน BSD Unix และ Linux ได้รับการพัฒนาให้ใช้งานร่วมกับ Unix ได้ดังนั้นระบบปฏิบัติการทั้งสองจึงได้รับการสืบทอดแบบแผนพฤติกรรมและเครื่องมือแบบเดียวกัน

Windows ไม่ได้รับการพัฒนาให้รองรับ Unix ดังนั้นจึงไม่มีแบบแผนเดียวกันและซอฟต์แวร์ Windows ส่วนใหญ่จะทำงานได้ดีโดยไม่ต้องขึ้นบรรทัดใหม่

แต่เนื่องจาก Git ได้รับการพัฒนาสำหรับ Linux ก่อนและซอฟต์แวร์โอเพนซอร์ซจำนวนมากถูกสร้างขึ้นบนระบบที่เข้ากันได้กับ Unix เช่น Linux, Mac OS X, FreeBSD เป็นต้นชุมชนโอเพ่นซอร์สส่วนใหญ่และเครื่องมือของพวกเขา (รวมถึงภาษาโปรแกรม) เพื่อทำตามอนุสัญญาเหล่านี้

มีเหตุผลทางเทคนิคที่ทำให้รู้สึกในปี 1971 แต่ในยุคนี้ส่วนใหญ่เป็นการประชุมและการบำรุงรักษาความเข้ากันได้กับเครื่องมือที่มีอยู่


23

หากคุณเพิ่มบรรทัดข้อความใหม่ในตอนท้ายของไฟล์ที่มีอยู่ซึ่งยังไม่มีnewline characterในตอนท้าย diff จะแสดงบรรทัดสุดท้ายเก่าว่ามีการแก้ไขแม้ว่าแนวคิดจะไม่ได้

นี่คือเหตุผลที่ดีอย่างน้อยหนึ่งข้อในการเพิ่ม newline characterจุดสิ้นสุด

ตัวอย่าง

ไฟล์ประกอบด้วย:

A() {
    // do something
}

hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d              something.}

ตอนนี้คุณแก้ไขเป็น

A() {
    // do something
}
// Useful comment

hexdump:

00000000: 4128 2920 7b0a 2020 2020 2f2f 2064 6f20  A() {.    // do 
00000010: 736f 6d65 7468 696e 670a 7d0a 2f2f 2055  something.}.// U
00000020: 7365 6675 6c20 636f 6d6d 656e 742e 0a    seful comment..

git diff จะแสดง:

-}
\ No newline at end of file
+}
+// Useful comment.

มันแสดงให้เห็นถึงความแตกต่างที่ใหญ่กว่าความคิดที่เกิดขึ้น มันแสดงให้เห็นว่าคุณลบบรรทัดและเพิ่มบรรทัด} }\nในความเป็นจริงสิ่งนี้เกิดขึ้น แต่ไม่ใช่สิ่งที่เกิดขึ้นในเชิงแนวคิดดังนั้นจึงอาจทำให้เกิดความสับสน


2
เราสามารถเขียนสิ่งเดียวกันในทิศทางอื่น: หากคุณลบบรรทัดใหม่ที่ท้ายไฟล์ที่มีอยู่ซึ่งมีการขึ้นบรรทัดใหม่ที่จุดสิ้นสุดแล้ว diff จะแสดงบรรทัดสุดท้ายเก่าที่ปรับเปลี่ยนเมื่อแนวคิดไม่ใช่ อย่างน้อยหนึ่งเหตุผลที่ดีในการลบบรรทัดใหม่ในตอนท้าย
gentiane

3
@gentiane คุณกำลังสับสน "บรรทัดใหม่" (ขึ้นบรรทัดใหม่) และ "ขึ้นบรรทัดใหม่" (1 หรือ 2 ตัวอักษรเพื่อกำหนดจุดสิ้นสุดของบรรทัด)
minexew

@minexew ไม่ gentiane ไม่ใช่ บางทีคุณอาจไม่ทราบว่า "บรรทัดใหม่" เหมือนกับ "ขึ้นบรรทัดใหม่"
เหลือเชื่อ

3
@TheincredibleJan วิธีที่พวกเขาใช้ในคำตอบทั้งสองคำมีความหมายที่แตกต่างกัน ฉันไม่รู้ว่าคุณกำลังพยายามที่จะเป็นคนฉลาดหรือเป็นเพียงความเข้าใจผิดว่าเกิดอะไรขึ้น
Minexew

18

มันเพิ่งระบุว่าจุดสิ้นสุดของไฟล์ไม่มีการขึ้นบรรทัดใหม่ ไม่ใช่ความหายนะมันเป็นเพียงข้อความที่จะทำให้ชัดเจนว่าไม่มีสิ่งใดเกิดขึ้นเมื่อมองไปที่บรรทัดคำสั่ง


10

เหตุผลที่การประชุมนี้เริ่มนำมาใช้จริงนั้นเป็นเพราะในระบบปฏิบัติการที่เหมือน UNIX ตัวอักขระขึ้นบรรทัดใหม่จะถือเป็นตัวยกเลิกบรรทัดและ / หรือขอบเขตของข้อความ (ซึ่งรวมถึงการไพพ์ระหว่างกระบวนการ

ตัวอย่างเช่นลองพิจารณาว่าไฟล์ที่มีเพียงอักขระบรรทัดใหม่จะถือว่าเป็นบรรทัดเดียวที่ว่างเปล่า ในทางกลับกันไฟล์ที่มีความยาวเป็นศูนย์ไบต์จะเป็นไฟล์เปล่าที่มีเส้นศูนย์ สิ่งนี้สามารถยืนยันได้ตามwc -lคำสั่ง

โดยสิ้นเชิงพฤติกรรมนี้มีเหตุผลเพราะจะไม่มีวิธีอื่นในการแยกแยะระหว่างไฟล์ข้อความที่ว่างเปล่ากับไฟล์ข้อความที่มีบรรทัดว่างเปล่าเพียงเส้นเดียวหาก\nตัวละครนั้นเป็นเพียงตัวแยกบรรทัดแทนที่จะเป็นตัวคั่นบรรทัด ดังนั้นไฟล์ข้อความที่ถูกต้องควรลงท้ายด้วยอักขระขึ้นบรรทัดใหม่ ข้อยกเว้นเพียงอย่างเดียวคือถ้าไฟล์ข้อความตั้งใจที่จะว่างเปล่า (ไม่มีบรรทัด)


1
ทำไมฉันถึงลงคะแนน -2 ฉันชี้ให้เห็นไม่เพียง แต่ยืนยันว่าคำตอบอื่น ๆ ได้ระบุไว้แล้ว (เช่นเครื่องมือที่ใช้มาตรฐาน UNIX คาดว่าจะมีการขึ้นบรรทัดใหม่เป็น terminator สำหรับบรรทัด) แต่ยังไม่มีวิธีแยกความแตกต่างของไฟล์เปล่าจากบรรทัดว่างเดียวซึ่งเป็นความจริงอย่างแน่นอน . ฉันตอบคำถามดั้งเดิมโดยเฉพาะ "ความสำคัญของข้อความคืออะไรและพยายามบอกเราอย่างไร"
Leslie Krause

ฉันไม่ได้ลงคะแนนคุณ แต่การตอบสนองนี้ดูเหมือนจะเฉพาะกับระบบพิมพ์ Unix ซึ่งจะใช้เฉพาะเมื่อขึ้นบรรทัดใหม่เป็นเพียงอักขระขึ้นบรรทัดใหม่ ไม่ชัดเจนว่าจะใช้กับที่นี่ นอกจากนี้คำเตือนยังดูเหมือนว่าไร้ประโยชน์หากไฟล์ประกอบด้วยเพียงบรรทัดว่าง อย่างไรก็ตามฉันหลีกเลี่ยง Stackoverflow เพราะคนมักจะลงคะแนนโดยไม่มีคำอธิบาย
user34660

9

มีสิ่งหนึ่งที่ฉันไม่เห็นในคำตอบก่อนหน้าคือ คำเตือนเกี่ยวกับการไม่สิ้นสุดบรรทัดอาจเป็นการเตือนเมื่อส่วนของไฟล์ถูกตัดทอน มันอาจเป็นอาการของข้อมูลที่หายไป


โดยทั่วไปแล้วจุดดี แต่ฉันไม่คิดว่ามันสมเหตุสมผลในบริบทของคำถามนี้
cst1992

@ cst1992 รู้รอบใน Stackoverflow น่าจะมีประโยชน์ที่สุดเท่าที่จะเป็นไปได้ซึ่งหมายความว่าควรจะใช้กับความเป็นไปได้ทั้งหมด คำถามนั้นสั้นและฉันไม่เห็นว่าจะแยกความเป็นไปได้ที่ฉันแนะนำ
user34660

7

ปัญหาหลักคือสิ่งที่คุณกำหนดเส้นและไม่ว่าลำดับตัวละครปลายสายเป็นส่วนหนึ่งของสายหรือไม่ เครื่องมือแก้ไขที่ใช้ UNIX (เช่น VIM) หรือเครื่องมือ (เช่น Git) ใช้ลำดับอักขระ EOL เป็นตัวยกเลิกบรรทัดดังนั้นจึงเป็นส่วนหนึ่งของบรรทัด มันคล้ายกับการใช้เซมิโคลอน (;) ใน C และ Pascal ใน C เครื่องหมายอัฒภาคยุติคำสั่งใน Pascal มันแยกพวกเขา


4

สิ่งนี้จะทำให้เกิดปัญหาเนื่องจากการสิ้นสุดบรรทัดถูกแก้ไขไฟล์สกปรกโดยอัตโนมัติโดยไม่ทำการเปลี่ยนแปลงใด ๆ ดูโพสต์นี้สำหรับการแก้ปัญหา

git แทนที่ LF ด้วย CRLF


3

ไฟล์ที่มามักจะต่อกันด้วยเครื่องมือ (C, C ++: ไฟล์ส่วนหัว, Javascript: bundlers) หากคุณไม่ใช้อักขระบรรทัดใหม่คุณสามารถแนะนำข้อบกพร่องที่น่ารังเกียจ (โดยที่บรรทัดสุดท้ายของแหล่งข้อมูลหนึ่งถูกต่อกันกับบรรทัดแรกของไฟล์ต้นฉบับถัดไป) หวังว่าเครื่องมือซอร์สโค้ดทั้งหมดของ concat จะมีการแทรกบรรทัดใหม่ระหว่างไฟล์ที่ต่อกันอยู่แล้ว แต่ก็ไม่ได้เป็นเช่นนั้นเสมอไป

ประเด็นสำคัญของปัญหาคือ - ในภาษาส่วนใหญ่บรรทัดใหม่มีความหมายเชิงความหมายและจุดสิ้นสุดของไฟล์ไม่ใช่ภาษาที่กำหนดทางเลือกสำหรับอักขระขึ้นบรรทัดใหม่ ดังนั้นคุณควรยุติทุกคำสั่ง / การแสดงออกด้วยอักขระขึ้นบรรทัดใหม่ - รวมถึงตัวสุดท้าย


1
ใน C / C ++ คุณสามารถเขียนโครงการทั้งหมดของคุณในหนึ่งบรรทัด ไม่จำเป็นต้องขึ้นบรรทัดใหม่
เหลือเชื่อ

คุณสามารถเขียนโปรเจคทั้งหมดของคุณในหนึ่งบรรทัด ... หากคุณไม่ได้ใช้//สไตล์คอมเม้นท์ตรงกลางโค้ด
Doug Coburn

2

ไฟล์ต้นฉบับของคุณอาจไม่มีอักขระขึ้นบรรทัดใหม่

อย่างไรก็ตามบรรณาธิการบางคนเช่นgeditใน linux จะเพิ่มบรรทัดใหม่เมื่อสิ้นสุดไฟล์ คุณไม่สามารถกำจัดข้อความนี้ในขณะที่ใช้โปรแกรมแก้ไขประเภทนี้

สิ่งที่ฉันพยายามที่จะเอาชนะปัญหานี้คือการเปิดไฟล์ด้วยโปรแกรมแก้ไขโค้ด visual studio

เครื่องมือแก้ไขนี้แสดงบรรทัดสุดท้ายอย่างชัดเจนและคุณสามารถลบบรรทัดได้ตามต้องการ


0

สำหรับสิ่งที่คุ้มค่าฉันพบสิ่งนี้เมื่อฉันสร้างโครงการ IntelliJ บน Mac แล้วย้ายโครงการไปยังเครื่อง Windows ของฉัน ฉันต้องเปิดทุกไฟล์ด้วยตนเองและเปลี่ยนการตั้งค่าการเข้ารหัสที่ด้านล่างขวาของหน้าต่าง IntelliJ อาจจะไม่เกิดขึ้นกับคนส่วนใหญ่ถ้าใครที่อ่านคำถามนี้ แต่นั่นอาจช่วยฉันทำงานสองสามชั่วโมง ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.