टेक्स्ट फ़ाइलों को एक नई पंक्ति के साथ क्यों समाप्त होना चाहिए?


1466

मुझे लगता है कि यहां हर कोई इस कहावत से परिचित है कि सभी पाठ फाइलें एक नई पंक्ति के साथ समाप्त होनी चाहिए। मैंने वर्षों से इस "नियम" के बारे में जाना है लेकिन मुझे हमेशा आश्चर्य होता है - क्यों?


30
सिर्फ एक निपिक। यह फ़ाइल के अंत में एक "नई पंक्ति" नहीं है। यह अंतिम पंक्ति के अंत में एक "लाइन ब्रेक" है। संबंधित प्रश्न पर सबसे अच्छा उत्तर भी देखें: stackoverflow.com/questions/16222530/…
gcb

344
बस कुछ और नाइटपिक करने के लिए, उन्होंने वास्तव में "नई लाइन" नहीं लिखी, उन्होंने "न्यूलाइन" लिखा, जो सही है।
सिन्ड्रोम

5
परिचित नहीं है, लेकिन मुझे आश्चर्य है कि वास्तव में इसलिए है कि उन मामलों की संख्या जहां कि अति
सुंदर न्यूलाइन

2
मैं वर्तमान में सादा-पाठ डेटा लाइन-बाय-लाइन पार्स करने के लिए Node.js स्ट्रीम का उपयोग कर रहा हूं, और टर्मिनल लाइन-ब्रेक की कमी कष्टप्रद है, क्योंकि मुझे स्ट्रीम के इनपुट साइड समाप्त होने पर अतिरिक्त तर्क जोड़ना होगा / यह सुनिश्चित करने के लिए बंद किया जाता है कि अंतिम पंक्ति संसाधित हो गई है।
मार्क के कोवान

23
जिस तरह से यूनिक्स फ़ाइलों के अंत में अपने सामान्य व्यवहार का संबंध रखता है, वह इस प्रकार है: \ n वर्ण रेखाएँ शुरू नहीं करते; इसके बजाय, वे उन्हें समाप्त करते हैं। तो, \ n एक लाइन टर्मिनेटर है, लाइन सेपरेटर नहीं। पहली लाइन (सभी लाइनों की तरह) को इसे शुरू करने के लिए no \ n की आवश्यकता होती है। अंतिम पंक्ति (सभी लाइनों की तरह) को इसे समाप्त करने के लिए एक \ n की आवश्यकता है। फ़ाइल के अंत में एक \ n अतिरिक्त लाइन नहीं बनाता है। कभी-कभी, हालांकि, टेक्स्ट एडिटर वहां एक दृश्यमान रिक्त रेखा जोड़ देंगे। यहां तक ​​कि emacs भी ऐसा करता है, वैकल्पिक रूप से
मार्कबडलैकवेल

जवाबों:


1380

क्योंकि POSIX मानक एक पंक्ति को कैसे परिभाषित करता है :

3.206 लाइन
शून्य या अधिक गैर- <newline> वर्णों के साथ-साथ एक समाप्ति <newline> वर्ण का क्रम।

इसलिए, एक नई पंक्ति में समाप्त नहीं होने वाली रेखाओं को वास्तविक रेखा नहीं माना जाता है। इसीलिए कुछ प्रोग्रामों में फ़ाइल की अंतिम पंक्ति को संसाधित करने में समस्याएँ होती हैं, यदि यह नई पंक्तिबद्ध नहीं है।

टर्मिनल एमुलेटर पर काम करते समय इस दिशानिर्देश का कम से कम एक कठिन लाभ है: सभी यूनिक्स उपकरण इस सम्मेलन की अपेक्षा करते हैं और इसके साथ काम करते हैं। उदाहरण के लिए, जब फाइलों को catसमाप्‍त किया जाता है, तो नईलाइन द्वारा समाप्‍त की गई फ़ाइल का एक के बिना एक अलग प्रभाव होगा:

$ more a.txt
foo
$ more b.txt
bar$ more c.txt
baz
$ cat {a,b,c}.txt
foo
barbaz

और, जैसा कि पिछले उदाहरण में भी दिखाया गया है, जब कमांड लाइन (उदाहरण के माध्यम से more) पर फ़ाइल प्रदर्शित करते हैं , तो एक नई-लाइन समाप्त फ़ाइल एक सही प्रदर्शन में परिणाम देती है। अनुचित तरीके से समाप्त की गई फ़ाइल को दूसरी पंक्ति में रखा जा सकता है।

स्थिरता के लिए, इस नियम का पालन करना बहुत सहायक है - अन्यथा डिफ़ॉल्ट यूनिक्स टूल के साथ काम करने पर अतिरिक्त काम करना होगा।


इसके बारे में अलग तरह से सोचें: यदि लाइनों को न्यूलाइन द्वारा समाप्त नहीं किया जाता है, तो कमांड जैसे कि catउपयोगी बनाना बहुत कठिन है: आप फ़ाइलों को संक्षिप्त करने के लिए एक कमांड कैसे बनाते हैं

  1. यह प्रत्येक फ़ाइल की शुरुआत को एक नई लाइन पर रखता है, जो कि आप 95% समय चाहते हैं; परंतु
  2. यह दो फाइलों की अंतिम और पहली पंक्ति को मिलाने की अनुमति देता है, जैसा कि ऊपर b.txtऔर नीचे के उदाहरण में है c.txt?

बेशक यह हल करने योग्य है, लेकिन आपको catअधिक जटिल का उपयोग करने की जरूरत है (स्थितीय कमांड लाइन तर्क जोड़कर, उदाहरण के लिए cat a.txt --no-newline b.txt c.txt), और अब प्रत्येक व्यक्तिगत फ़ाइल के बजाय कमांड यह नियंत्रित करता है कि इसे अन्य फ़ाइलों के साथ कैसे चिपकाया जाता है। यह लगभग निश्चित रूप से सुविधाजनक नहीं है।

… या आपको एक पंक्ति को चिह्नित करने के लिए एक विशेष प्रहरी वर्ण शुरू करने की आवश्यकता है जिसे समाप्त करने के बजाय जारी रखना चाहिए। ठीक है, अब आप POSIX पर उसी स्थिति के साथ फंस गए हैं, सिवाय उलटे (लाइन समाप्ति वर्ण के बजाय लाइन निरंतरता)।


अब, गैर POSIX आज्ञाकारी प्रणालियों पर (आजकल जो कि ज्यादातर विंडोज है), बिंदु मूट है: फाइलें आम तौर पर एक नई पंक्ति के साथ समाप्त नहीं होती हैं, और उदाहरण के लिए एक पंक्ति की (अनौपचारिक) परिभाषा "पाठ जो newlines द्वारा अलग की जाती है" हो सकती है (जोर पर ध्यान दें)। यह पूरी तरह से वैध है। हालांकि, संरचित डेटा (जैसे प्रोग्रामिंग कोड) के लिए यह पार्सिंग को न्यूनतम रूप से अधिक जटिल बनाता है: इसका आमतौर पर मतलब है कि पार्सर्स को फिर से लिखना होगा। यदि कोई पार्सर मूल रूप से पॉसिक्स परिभाषा को ध्यान में रखकर लिखा गया था, तो हो सकता है कि पार्सर के बजाय टोकन स्ट्रीम को संशोधित करना आसान हो - दूसरे शब्दों में, इनपुट के अंत में एक "कृत्रिम नई लाइन" टोकन जोड़ें।


7
यद्यपि अब इसे सुधारने के लिए काफी अव्यवहारिक है, स्पष्ट रूप से POSIX ने लाइन को परिभाषित करते समय एक गलती की - इस मुद्दे के बारे में प्रश्नों की संख्या से सबूत के रूप में। एक पंक्ति को <eol>, <eof>, या <eol> <of> द्वारा समाप्त शून्य या अधिक वर्णों के रूप में परिभाषित किया जाना चाहिए। पार्सर जटिलता एक वैध चिंता का विषय नहीं है। जहां भी संभव हो, जटिलता को प्रोग्रामर के सिर से और लाइब्रेरी में स्थानांतरित किया जाना चाहिए।
डग कोबर्न

22
@DougCoburn इस उत्तर में एक संपूर्ण, तकनीकी चर्चा का उपयोग किया गया था जिसमें बताया गया था कि यह गलत क्यों है, और POSIX ने सही काम क्यों किया। दुर्भाग्य से इन टिप्पणियों को हाल ही में एक भारी मध्यस्थ द्वारा हटा दिया गया था। संक्षेप में, यह पार्सिंग जटिलता के बारे में नहीं है; बल्कि, आपकी परिभाषा लेखक के औजारों को बहुत कठिन बनाती है जैसे catकि यह उपयोगी और सुसंगत दोनों है।
कोनराड रुडोल्फ

8
@ लिसन POSIX नियम किनारे के मामलों को कम करने के बारे में है। और यह इतनी खूबसूरती से करता है। मैं वास्तव में कुछ हद तक एक नुकसान में हूं कि लोग इसे कैसे समझ सकते हैं: यह एक पंक्ति की सबसे सरल, आत्म-सुसंगत परिभाषा है।
कोनराड रुडोल्फ

6
@BT मैं तुम्हें यह सोचते रहे कि मेरी लगता है उदाहरण के एक और अधिक सुविधाजनक कार्यप्रवाह का है कारण फैसले के पीछे। यह नहीं है, यह सिर्फ एक परिणाम है। कारण है कि POSIX नियम नियम यह है कि सरल है है, और जो एक पार्सर सबसे आसान में से निपटने लाइनों बनाता है। एकमात्र कारण यह है कि हम बहस कर रहे हैं कि विंडोज इसे अलग तरीके से करता है, और इसके परिणामस्वरूप, कई उपकरण हैं जो POSIX फ़ाइलों पर विफल हैं। अगर हर कोई POSIX करता, तो कोई समस्या नहीं होती। फिर भी लोग POSIX के बारे में शिकायत करते हैं, विंडोज के बारे में नहीं।
कोनराड रुडोल्फ

7
@BT मैं केवल उन मामलों को इंगित करने के लिए Windows का उल्लेख कर रहा हूं जहां POSIX नियमों का कोई मतलब नहीं है (दूसरे शब्दों में, मैं आपको एक हड्डी फेंक रहा था)। मैं इस चर्चा में फिर से इसका उल्लेख नहीं करने से ज्यादा खुश हूं। लेकिन तब आपका दावा और भी कम समझ में आता है: POSIX प्लेटफ़ॉर्म पर यह अलग लाइन खत्म करने वाले सम्मेलनों के साथ पाठ फ़ाइलों पर चर्चा करने का कोई मतलब नहीं है, क्योंकि उनके उत्पादन का कोई कारण नहीं है। फायदा क्या है? सचमुच कोई नहीं है। - संक्षेप में, मैं वास्तव में इस जवाब (या पॉसिक्स नियम) से नफरत नहीं समझ रहा हूं । फ्रैंक होना, यह पूरी तरह से तर्कहीन है।
कोनराड रुडोल्फ

282

प्रत्येक पंक्ति को एक नए वर्ण में समाप्त किया जाना चाहिए, जिसमें अंतिम एक भी शामिल है। कुछ प्रोग्राम में फ़ाइल की अंतिम पंक्ति को संसाधित करने में समस्याएँ होती हैं, यदि यह नई पंक्तिबद्ध नहीं है।

क्योंकि यह जीसीसी नहीं इसके बारे में चेतावनी दी है नहीं कर सकते हैं फ़ाइल पर कार्रवाई, लेकिन क्योंकि यह करना पड़ता है मानक के हिस्से के रूप।

C भाषा मानक कहता है कि एक स्रोत फ़ाइल जो खाली नहीं है, एक नई-पंक्ति वर्ण में समाप्त हो जाएगी, जो तुरंत बैकस्लैश वर्ण से पहले नहीं होगी।

चूंकि यह "करेगा" खंड है, इसलिए हमें इस नियम के उल्लंघन के लिए एक नैदानिक ​​संदेश का उत्सर्जन करना चाहिए।

यह ANSI C 1989 मानक के खंड 2.1.1.2 में है। आईएसओ सी 1999 मानक की धारा 5.1.1.2 (और शायद आईएसओ सी 1990 मानक भी)।

संदर्भ: GCC / GNU मेल संग्रह


17
कृपया अच्छे कार्यक्रम लिखें, ताकि या तो उस नई लाइन को डालने की अनुमति दें जहाँ प्रसंस्करण के दौरान ज़रूरत हो या "लापता" को ठीक से संभालने में सक्षम हों ... जो वास्तव में, गायब नहीं हैं
Tobibeer

4
@BilltheLizard, "कुछ प्रोग्राम्स को फ़ाइल की अंतिम पंक्ति को संसाधित करने में समस्याएँ आती हैं, अगर इसे नई पंक्तिबद्ध नहीं किया गया है " तो क्या उदाहरण हैं ?
पैशियर

4
@Pacerier wc -lएक फ़ाइल की अंतिम पंक्ति की गणना नहीं करेगा यदि यह नई पंक्तिबद्ध नहीं है। इसके अलावा, catअगली फ़ाइल की पहली पंक्ति के साथ एक फ़ाइल की अंतिम पंक्ति में शामिल हो जाएगा अगर पहली फ़ाइल की अंतिम पंक्ति को नई पंक्तिबद्ध नहीं किया गया है। बहुत ज्यादा है कि किसी भी कार्यक्रम के रूप में नए सिरे से खोज रहा है एक अपराधी के रूप में यह गड़बड़ करने की क्षमता है।
छिपकली

2
@BilltheLizard, मेरा मतलब है wcकि पहले ही उल्लेख किया गया है ....
Pacerier

2
@BilltheLizard, मेरा बुरा, स्पष्ट करने के लिए: प्रोग्राम के कुछ उदाहरण हैं जिन्हें समस्या की एक फ़ाइल की अंतिम पंक्ति को संसाधित करने में समस्या होती है यदि यह नईलाइन समाप्त नहीं हुई है (इसके अलावा जो पहले से ही थ्रेड पर बड़े पैमाने पर उल्लेखित हैं ) catऔर wc?
पचेरियर

116

यह उत्तर राय के बजाय तकनीकी उत्तर का प्रयास है।

यदि हम POSIX शुद्धतावादी बनना चाहते हैं, तो हम एक पंक्ति को इस प्रकार परिभाषित करते हैं:

शून्य या अधिक गैर- <newline> वर्णों के साथ-साथ एक समाप्ति <newline> वर्ण का क्रम।

स्रोत: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206

एक अपूर्ण रेखा इस प्रकार है:

फ़ाइल के अंत में एक या अधिक गैर- <newline> वर्णों का एक क्रम।

स्रोत: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_195

एक पाठ फ़ाइल के रूप में:

एक फ़ाइल जिसमें वर्ण शून्य या अधिक लाइनों में व्यवस्थित होते हैं। लाइनों में NUL वर्ण नहीं होते हैं और कोई भी <newline> वर्ण सहित, लंबाई में {LINE_MAX} बाइट्स से अधिक नहीं हो सकता है। यद्यपि POSIX.1-2008 पाठ फ़ाइलों और बाइनरी फ़ाइलों (आईएसओ सी मानक देखें) के बीच अंतर नहीं करता है, कई उपयोगिताओं केवल पाठ फ़ाइलों पर काम करते समय अनुमानित या सार्थक आउटपुट उत्पन्न करती हैं। मानक उपयोगिताओं जिनके पास इस तरह के प्रतिबंध हैं, हमेशा अपने STDIN या INPUT FILES अनुभागों में "पाठ फ़ाइलों" को निर्दिष्ट करते हैं।

स्रोत: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_397

एक स्ट्रिंग के रूप में:

बाइट्स के एक सन्निहित अनुक्रम को पहले शून्य बाइट सहित और समाप्त किया गया।

स्रोत: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_396

इसके बाद से, हम यह प्राप्त कर सकते हैं कि केवल उसी समय जब हम संभावित रूप से किसी भी प्रकार के मुद्दों का सामना करेंगे, यदि हम एक फ़ाइल की एक पंक्ति या एक पाठ फ़ाइल के रूप में एक फ़ाइल की अवधारणा के साथ काम करते हैं (जा रहा है कि एक पाठ फ़ाइल शून्य का एक संगठन है या अधिक पंक्तियाँ, और एक पंक्ति जिसे हम जानते हैं कि <newline>) के साथ समाप्त होना चाहिए।

इसका स्पष्ट उदाहरण: wc -l filename

से wcकी पुस्तिका हम पढ़ते हैं:

एक पंक्ति को <newline> वर्ण द्वारा सीमांकित वर्णों की एक स्ट्रिंग के रूप में परिभाषित किया गया है।

जावास्क्रिप्ट, एचटीएमएल और सीएसएस फ़ाइलों के क्या निहितार्थ हैं, फिर यह कि वे पाठ हैं फाइलें हैं?

ब्राउज़रों में, आधुनिक आईडीई और अन्य फ्रंट-एंड एप्लिकेशन में ईओएफ पर ईओएल को छोड़ने के साथ कोई समस्या नहीं है। एप्लिकेशन ठीक से फ़ाइलों को पार्स करेंगे। चूंकि सभी ऑपरेटिंग सिस्टम को POSIX मानक के अनुरूप नहीं है, इसलिए POSIX मानक (या किसी भी OS- स्तर मानक) के अनुसार फ़ाइलों को संभालने के लिए गैर-OS उपकरण (जैसे ब्राउज़र) के लिए यह अव्यावहारिक होगा।

नतीजतन, हम अपेक्षाकृत आश्वस्त हो सकते हैं कि ईओएफ पर ईओएल का आवेदन स्तर पर लगभग कोई नकारात्मक प्रभाव नहीं होगा - भले ही यह यूनिक्स के ओएस पर चल रहा हो।

इस बिंदु पर हम विश्वास के साथ कह सकते हैं कि ग्राहक पक्ष पर जेएस, एचटीएमएल, सीएसएस के साथ काम करते समय ईओएफ पर ईओएल को छोड़ना सुरक्षित है। दरअसल, हम यह बता सकते हैं कि इनमें से किसी भी फाइल को छोटा करना, जिसमें कोई <newline> सुरक्षित नहीं है।

हम इसे एक कदम आगे ले जा सकते हैं और कह सकते हैं कि जहां तक ​​NodeJS का संबंध है, यह भी POSIX मानक का पालन नहीं कर सकता है कि यह गैर-POSIX अनुरूप वातावरण में चल सकता है।

फिर हम क्या बचे हैं? सिस्टम स्तर टूलींग।

इसका मतलब यह है कि उत्पन्न होने वाले एकमात्र मुद्दे उन उपकरणों के साथ हैं जो पोसिक्स के शब्दार्थों के लिए अपनी कार्यक्षमता का पालन करने का प्रयास करते हैं (उदाहरण के लिए एक पंक्ति की परिभाषा जैसा कि दिखाया गया है) wc )।

फिर भी, सभी गोले स्वचालित रूप से POSIX का पालन नहीं करेंगे। उदाहरण के लिए बैश POSIX व्यवहार के लिए डिफ़ॉल्ट नहीं है। इसे सक्षम करने के लिए एक स्विच है:POSIXLY_CORRECT :।

EOL के मूल्य पर विचार के लिए भोजन <newline>: https://www.rfc-editor.org/old/EOLFory.txt

सभी व्यावहारिक इरादों और उद्देश्यों के लिए टूलिंग ट्रैक पर बने रहें, आइए इस पर विचार करें:

आइए ऐसी फ़ाइल के साथ काम करें जिसमें कोई EOL नहीं है। जैसा कि इस उदाहरण में फ़ाइल को लिखना एक छोटा जावास्क्रिप्ट है जिसमें कोई ईओएल नहीं है।

curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o x.js
curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o y.js

$ cat x.js y.js > z.js

-rw-r--r--  1 milanadamovsky   7905 Aug 14 23:17 x.js
-rw-r--r--  1 milanadamovsky   7905 Aug 14 23:17 y.js
-rw-r--r--  1 milanadamovsky  15810 Aug 14 23:18 z.js

ध्यान दें कि catफ़ाइल का आकार इसके व्यक्तिगत भागों का योग है। यदि जावास्क्रिप्ट फ़ाइलों का संयोजन जेएस फाइलों के लिए एक चिंता का विषय है, तो अधिक उपयुक्त चिंता प्रत्येक जावास्क्रिप्ट फाइल को अर्ध-कॉलन के साथ शुरू करने की होगी।

जैसा कि इस धागे में किसी और ने उल्लेख किया है: क्या होगा यदि आप catदो फाइलें चाहते हैं, जिनका आउटपुट दो के बजाय सिर्फ एक लाइन बन जाता है? दूसरे शब्दों में, catयह वही करता है जो करना चाहिए।

manके catकेवल EOF के लिए इनपुट अप पढ़ने का उल्लेख है, नहीं <न्यू लाइन>। ध्यान दें कि वसीयत का -nस्विच catएक गैर- <newline> टर्मिनेटेड लाइन (या अधूरी लाइन ) को एक लाइन के रूप में प्रिंट करेगा - यह माना जा रहा है कि गिनती 1 (के अनुसार man) से शुरू होती है ।

-एन आउटपुट लाइनों, 1 से शुरू।

अब जब हम समझते हैं कि POSIX एक पंक्ति को कैसे परिभाषित करता है , तो यह व्यवहार अस्पष्ट हो जाता है, या वास्तव में, गैर-अनुपालन।

किसी दिए गए टूल के उद्देश्य और अनुपालन को समझने से यह निर्धारित करने में मदद मिलेगी कि ईओएल के साथ फ़ाइलों को समाप्त करना कितना महत्वपूर्ण है। C, C ++, Java (JARs) आदि में ... कुछ मानक वैधता के लिए एक नई रूपरेखा तय करेंगे - JS, HTML, CSS के लिए ऐसा कोई मानक मौजूद नहीं है।

उदाहरण के लिए, wc -l filenameएक का उपयोग करने के बजाय awk '{x++}END{ print x}' filename, और यह आश्वासन दिया जा सकता है कि कार्य की सफलता एक फ़ाइल द्वारा खतरे में नहीं है जिसे हम संसाधित करना चाहते हैं कि हम लिख नहीं पाए (उदाहरण के लिए जेएस हम जैसे तृतीय पक्ष पुस्तकालय curl- d) आशय सही मायने में POSIX आज्ञाकारी अर्थों में लाइनों की गणना करना था ।

निष्कर्ष

ऐसे बहुत कम वास्तविक उपयोग के मामले होंगे जहां कुछ पाठ फ़ाइलों जैसे जेएस, एचटीएमएल और सीएसएस के लिए ईओएल पर ईओएल को छोड़ना एक नकारात्मक प्रभाव पड़ेगा - यदि बिल्कुल। यदि हम <newline> पर भरोसा करते हैं, तो हम अपनी टूलिंग की विश्वसनीयता को केवल उन फ़ाइलों तक सीमित कर रहे हैं, जिन्हें हम लेखक और तीसरे पक्ष की फाइलों द्वारा शुरू की गई संभावित त्रुटियों तक खोलते हैं।

कहानी का नैतिक: इंजीनियर टूलिंग जिसमें ईओएल पर ईओएल पर भरोसा करने की कमजोरी नहीं है।

जेएस, एचटीएमएल और सीएसएस पर लागू होने के बाद उपयोग के मामलों को बेझिझक करें जहां हम जांच कर सकते हैं कि ईओएल को कैसे छोड़ना एक प्रतिकूल प्रभाव है।


2
POSIX को प्रश्न में टैग नहीं किया गया है ... MVS / OS लाइन अंत के बारे में वाट? या एमएस-डॉस लाइन अंत? वैसे, सभी ज्ञात पॉज़िक्स सिस्टम एक अंतिम पंक्ति के बिना पाठ फ़ाइलों को समाप्त करने की अनुमति देते हैं (कोई भी मामला जो एक पॉज़िक्स आज्ञाकारी दावा प्रणाली के बारे में नहीं पाया गया है, जिस पर "टेक्स्ट फ़ाइल" के पास एक उचित नई रेखा सम्मिलित करने के लिए कर्नेल में विशेष उपचार नहीं होता है। यह)
लुइस कोलोराडो

62

यह बीच के अंतर से संबंधित हो सकता है :

  • पाठ फ़ाइल (प्रत्येक पंक्ति अंत-पंक्ति में समाप्त होने वाली है)
  • द्विआधारी फ़ाइल (बोलने के लिए कोई सच्ची "लाइनें" नहीं हैं, और फ़ाइल की लंबाई संरक्षित होनी चाहिए)

यदि प्रत्येक पंक्ति अंत-पंक्ति में समाप्त होती है, तो यह टालता है, उदाहरण के लिए, दो पाठ फ़ाइलों को संक्षिप्त करने से पहली पंक्ति की अंतिम पंक्ति दूसरी पंक्ति में पहली पंक्ति में आ जाएगी।

साथ ही, एक संपादक लोड की जांच कर सकता है कि क्या फ़ाइल एंड-ऑफ़-लाइन में समाप्त होती है, इसे अपने स्थानीय विकल्प 'ईओएल' में बचाता है, और फ़ाइल लिखते समय इसका उपयोग करता है।

कुछ साल पहले (2005), कई संपादकों (ZDE, Eclipse, Scite, ...) ने उस अंतिम ईओएल को "भूल" किया, जो बहुत सराहा नहीं गया था
इतना ही नहीं, लेकिन उन्होंने उस अंतिम ईओएल को गलत तरीके से व्याख्या किया, जैसा कि 'एक नई लाइन शुरू करें', और वास्तव में एक और लाइन प्रदर्शित करना शुरू कर देता है जैसे कि यह पहले से मौजूद है।
यह उपरोक्त संपादकों में से एक को खोलने की तुलना में विम जैसे एक अच्छी तरह से व्यवहार किए गए पाठ संपादक के साथ एक 'उचित' टेक्स्ट फ़ाइल के साथ बहुत ही स्पष्ट था। यह फ़ाइल की वास्तविक अंतिम पंक्ति के नीचे एक अतिरिक्त रेखा प्रदर्शित करता है। आप कुछ इस तरह देखते हैं:

1 first line
2 middle line
3 last line
4

11
+1। मुझे यह बहुत समस्या का अनुभव करते हुए SO प्रश्न मिला है। यह "नकली" अंतिम पंक्ति दिखाने के लिए ग्रहण का बहुत गुस्सा है, और अगर मैं इसे हटा देता हूं, तो गिट (और ईओएल की उम्मीद करने वाले अन्य सभी यूनिक्स उपकरण) शिकायत करते हैं। इसके अलावा, ध्यान दें कि यह न केवल 2005 में है: ग्रहण 4.2 जूनो में अभी भी यह मुद्दा है।
MestreLion


46

कुछ उपकरण इसकी उम्मीद करते हैं। उदाहरण के लिए, wcयह अपेक्षा करता है:

$ echo -n "Line not ending in a new line" | wc -l
0
$ echo "Line ending with a new line" | wc -l
1

22
मैं "कुछ" नहीं कहूंगा, मैं कहता हूं कि अधिकांश उपकरण उम्मीद करते हैं कि पाठ फ़ाइलों के लिए, यदि सभी नहीं। cat, git, diff, wc, grep, sed ... सूची बहुत बड़ी है
MestreLion

शायद कोई यह कह सकता है कि wcयह उम्मीद नहीं करता है , जितना कि यह "लाइन" के पॉज़िक्स परिभाषा के भीतर काम कर रहा है, जैसा कि "लाइन" के अधिकांश लोगों की सहज समझ के विपरीत है।
गिल्डनस्टर्न

@Guildenstern सहज परिभाषा दोनों मामलों में wc -lमुद्रित करने के लिए होगी 1, लेकिन कुछ लोग कह सकते हैं कि दूसरे मामले को प्रिंट करना चाहिए 2
फ्लिम

@ फ्लीम यदि आप \nएक लाइन टर्मिनेटर के रूप में सोचते हैं , बल्कि एक लाइन विभाजक के रूप में, जैसा कि POSIX / UNIX करता है, तो 2 प्रिंट करने के लिए दूसरे मामले की अपेक्षा करना बिल्कुल पागल है।
अर्धविराम

21

मूल रूप से ऐसे कई कार्यक्रम हैं जो अंतिम ईओएल ईओएफ नहीं मिलने पर फाइलों को सही ढंग से संसाधित नहीं करेंगे।

जीसीसी आपको इस बारे में चेतावनी देता है क्योंकि यह सी मानक के हिस्से के रूप में अपेक्षित है। (खंड 5.1.1.2 जाहिरा तौर पर)

"फ़ाइल के अंत में कोई नई पंक्ति नहीं" संकलक चेतावनी


5
जीसीसी फ़ाइल को संसाधित करने में असमर्थ है, इसे सी मानक के भाग के रूप में चेतावनी देनी होगी।
छिपकली का बिल

IIRC, MSVC 2005 ने सी फाइलों के बारे में शिकायत की जो अपूर्ण लाइनों के साथ समाप्त हो गई और संभवतः उन्हें संकलित करने से इनकार कर दिया।
मार्क के कोवान

16

यह शुरुआती दिनों से शुरू होता है जब सरल टर्मिनलों का उपयोग किया जाता था। नईलाइन चार्ट का उपयोग स्थानांतरित डेटा के 'फ्लश' को ट्रिगर करने के लिए किया गया था।

आज, नई लाइन चार की आवश्यकता नहीं है। निश्चित रूप से, यदि नयालाइन नहीं है, तो कई ऐप्स को अभी भी समस्या है, लेकिन मैं उन ऐप्स में बग पर विचार करूंगा।

यदि आपके पास एक पाठ फ़ाइल प्रारूप है जहाँ आपको नई लाइन की आवश्यकता होती है, तो आपको सरल डेटा सत्यापन बहुत सस्ता मिलता है: यदि फ़ाइल एक पंक्ति के साथ समाप्त होती है जिसमें अंत में कोई नई रेखा नहीं है, तो आप जानते हैं कि फ़ाइल टूट गई है। प्रत्येक पंक्ति के लिए केवल एक अतिरिक्त बाइट के साथ, आप उच्च सटीकता और लगभग कोई सीपीयू समय के साथ टूटी हुई फ़ाइलों का पता लगा सकते हैं।


15
आजकल टेक्स्ट फ़ाइलों के लिए ईओएफ में नई लाइन एक आवश्यकता नहीं हो सकती है, लेकिन यह एक उपयोगी सम्मेलन है जो अधिकांश यूनिक्स टूल को लगातार परिणामों के साथ मिलकर काम करता है। यह एक बग बिल्कुल नहीं है।
MestreLion

14
हम में से बहुत सारे यूनिक्स उपकरणों का उपयोग नहीं करते हैं, और हम परवाह नहीं करते हैं।
डेववले

12
यह सिर्फ यूनिक्स उपकरण नहीं है, कोई भी उपकरण बेहतर काम करेगा और / या अधिक कोडित किया जा सकता है अगर यह समझदार फ़ाइल स्वरूपों को ग्रहण कर सकता है।
सैम वाटकिंस

2
@ सॅम वाटकिंस सहमत हैं कि अच्छी तरह से परिभाषित प्रारूप अच्छे हैं। फिर भी कोड को अभी भी सत्यता की आवश्यकता है, और नहीं मान लें, डेटा प्रारूप अनुरूप है।
चक्स - मोनिका

8
@MestreLion यह बेकार उपकरणों के एक सेट से एक बेकार विरासत है जो बेवकूफ मानकों के अनुरूप है। चरमपंथी प्रोग्रामिंग की ये कलाकृतियाँ (यानी सब कुछ फ़ाइल! सब कुछ सादे पाठ से बात करना चाहिए!) उनके आविष्कार के तुरंत बाद मर नहीं गया क्योंकि वे इतिहास के एक निश्चित क्षण में इस तरह के एकमात्र उपलब्ध उपकरण थे। C को C ++ द्वारा अलग किया गया था, यह POSIX का हिस्सा नहीं है, इसके लिए EOF पर EOL की आवश्यकता नहीं है, और इसका उपयोग (स्पष्ट रूप से) * nix luddists द्वारा हतोत्साहित किया गया है।
polkovnikov.ph

14

एक अलग उपयोग का मामला: जब आपकी पाठ फ़ाइल संस्करण नियंत्रित होती है (विशेष रूप से इस मामले में, हालांकि यह दूसरों पर भी लागू होती है)। यदि सामग्री को फ़ाइल के अंत में जोड़ा जाता है, तो जो लाइन पहले अंतिम पंक्ति थी, उसे एक नई लाइन वर्ण शामिल करने के लिए संपादित किया जाएगा। इसका मतलब यह है कि blameफ़ाइल को यह पता लगाने के लिए कि उस पंक्ति को अंतिम बार कब संपादित किया गया था, पाठ जोड़ दिखाएगा, न कि इससे पहले कि आप वास्तव में देखना चाहते थे।


1
"नई पंक्तियों" ( \n) के बजाय "नई पंक्तियों" का पता लगाने के लिए अंतर और दोष को अद्यतन किया जाना चाहिए । समस्या सुलझ गयी।
एंड्रयू

1
आप व्हाट्सएप परिवर्तन को अनदेखा करने के लिए -w टैग का उपयोग कर सकते हैं, लेकिन वे डिफ़ॉल्ट नहीं हैं।
रॉबिन व्हिटलटन

11

उपरोक्त व्यावहारिक कारणों के अलावा, यदि यूनिक्स (थॉम्पसन, रिची, एट अल।) या उनके मल्टिक्स पूर्ववर्तियों के प्रवर्तकों ने महसूस किया कि लाइन विभाजक के बजाय लाइन टर्मिनेटर का उपयोग करने का एक सैद्धांतिक कारण है तो यह मुझे आश्चर्यचकित नहीं करेगा। टर्मिनेटर, आप लाइनों की सभी संभव फ़ाइलों को सांकेतिक शब्दों में बदलना कर सकते हैं। लाइन विभाजकों के साथ, शून्य लाइनों की फाइल और सिंगल खाली लाइन वाली फाइल में कोई अंतर नहीं है; वे दोनों शून्य वर्ण वाली फ़ाइल के रूप में एन्कोडेड हैं।

तो, कारण हैं:

  1. क्योंकि जिस तरह से POSIX इसे परिभाषित करता है।
  2. क्योंकि कुछ उपकरण इसके बिना या "दुर्व्यवहार" की उम्मीद करते हैं। उदाहरण के लिए,wc -l एक अंतिम "लाइन" नहीं गिना जाएगा यदि यह एक नई रेखा के साथ समाप्त नहीं होता है।
  3. क्योंकि यह सरल और सुविधाजनक है। यूनिक्स पर, catबस काम करता है और यह जटिलता के बिना काम करता है। यह सिर्फ व्याख्या के लिए किसी भी आवश्यकता के बिना, प्रत्येक फ़ाइल के बाइट्स को कॉपी करता है। मुझे नहीं लगता कि इसके बराबर कोई डॉस है cat। उपयोग copy a+b cकरने से फ़ाइल aकी पहली पंक्ति के साथ फ़ाइल की अंतिम पंक्ति का विलय हो जाएगाb
  4. क्योंकि शून्य लाइनों की एक फ़ाइल (या स्ट्रीम) को एक खाली लाइन की एक फ़ाइल से अलग किया जा सकता है।

11

मैंने वर्षों से खुद को आश्चर्यचकित किया है। लेकिन मैं आज एक अच्छे कारण के साथ आया हूं।

हर लाइन पर रिकॉर्ड के साथ फाइल की कल्पना करें (उदा: CSV फ़ाइल)। और यह कि कंप्यूटर फ़ाइल के अंत में रिकॉर्ड लिख रहा था। लेकिन यह अचानक दुर्घटनाग्रस्त हो गया। Gee अंतिम पंक्ति थी? (अच्छी स्थिति नहीं)

लेकिन अगर हम हमेशा अंतिम पंक्ति को समाप्त करते हैं, तो हमें पता होगा (बस अंतिम पंक्ति समाप्त होने पर जांच लें)। अन्यथा हमें शायद हर बार अंतिम पंक्ति को त्यागना होगा, बस सुरक्षित रहने के लिए।


10

मुमकिन है कि कुछ पार्सिंग कोड की उम्मीद है कि यह वहाँ होगा।

मुझे यकीन नहीं है कि मैं इसे "नियम" मानूंगा, और यह निश्चित रूप से ऐसा कुछ नहीं है जिसे मैं धार्मिक रूप से मानता हूं। अधिकांश समझदार कोड को पता होगा कि पाठ को कैसे पार्स करना है (एन्कोडिंग सहित) लाइन-बाय-लाइन (लाइन एंडिंग का कोई विकल्प), अंतिम पंक्ति पर एक नई रेखा के साथ या बिना।

वास्तव में - यदि आप एक नई रेखा के साथ समाप्त होते हैं: क्या ईओएल और ईओएफ के बीच एक खाली अंतिम रेखा है? एक से विचार करना ...


12
यह एक नियम नहीं है, यह एक कन्वेंशन है: एक लाइन एक ऐसी चीज है जो एंड-ऑफ-लाइन के साथ समाप्त होती है । तो नहीं, EOL और EOF के बीच कोई "खाली अंतिम पंक्ति" नहीं है।
MestreLion

4
@MestreLion: लेकिन विचाराधीन चरित्र का नाम "एंड-ऑफ़-लाइन" नहीं है, इसे "न्यूलाइन" और / या "लाइनफ़ीड" नाम दिया गया है। एक लाइन विभाजक, एक लाइन टर्मिनेटर नहीं। और परिणाम एक अंतिम खाली लाइन है।
बेन वोइगट

2
नो (साने) टूल एक अतिरिक्त, खाली लाइन के रूप में एक फ़ाइल के अंतिम ईओएल (सीआर, एलएफ, आदि) की गणना करेगा। और सभी POSIX उपकरण फ़ाइल के अंतिम वर्णों को एक पंक्ति के रूप में नहीं गिनेंगे यदि कोई अंतिम ईओएल नहीं है। ईओएल चरित्र नाम के बावजूद "लाइन फीड" या "कैरिज रिटर्न" (इसमें "न्यूलाइन" नाम का कोई चरित्र नहीं है), सभी व्यावहारिक विद्यार्थियों के लिए समझदार उपकरण इसे लाइन टर्मिनेटर के रूप में मानते हैं , लाइन विभाजक के रूप में नहीं ।
MestreLion

2
@MestreLion, क्या आप सुनिश्चित हैं कि "लाइन टर्मिनेटर" समझदार है? कुछ गैर-प्रोग्रामर को पकड़ो और एक त्वरित सर्वेक्षण करें। आपको जल्दी से एहसास होगा कि लाइनों की अवधारणा "लाइन सेपरेटर्स" की अवधारणा के करीब है। "लाइन टर्मिनेटर" की अवधारणा सिर्फ अजीब है
पचेरियर

4
@Sahuagin: यह मेरा विचार नहीं है , यह कैसे POSIX मानक एक पंक्ति को परिभाषित करता है। 0 बाइट्स के साथ एक खाली फ़ाइल 0 लाइनों, इसलिए कोई EOL है, और एक फ़ाइल बस एक ही, रिक्त पंक्ति होने के रूप में विचार किया जाना है, यह करता है एक EOL आवश्यकता होती है। यह भी नोट करें कि यह केवल तभी प्रासंगिक है जब आप किसी फ़ाइल पर लाइनों को गिनना चाहते हैं , जैसा कि स्पष्ट रूप से कोई भी संपादक आपको अगली (या पहली) पंक्ति को "प्राप्त" करने देगा चाहे कोई भी ईओएल वहां पहले से मौजूद हो।
MestreLion

10

अंत में newlines की कमी वाली फ़ाइलों के साथ एक व्यावहारिक प्रोग्रामिंग मुद्दा भी है: द readबैश बिल्ट-इन (मुझे अन्य readकार्यान्वयन के बारे में पता नहीं है ) उम्मीद के मुताबिक काम नहीं करता है:

printf $'foo\nbar' | while read line
do
    echo $line
done

यह केवलfoo प्रिंट करता है ! कारण यह है कि जब readअंतिम पंक्ति का सामना होता है, तो यह सामग्री को लिखता है, $lineलेकिन निकास कोड 1 लौटाता है क्योंकि यह ईओएफ तक पहुंच गया है। यह whileलूप को तोड़ता है , इसलिए हम कभी भी echo $lineभाग तक नहीं पहुंचते हैं । यदि आप इस स्थिति को संभालना चाहते हैं, तो आपको निम्नलिखित कार्य करने होंगे:

while read line || [ -n "${line-}" ]
do
    echo $line
done < <(printf $'foo\nbar')

यही है, echoअगर readफ़ाइल के अंत में एक गैर-रिक्त रेखा के कारण विफल हुआ है। स्वाभाविक रूप से, इस मामले में आउटपुट में एक अतिरिक्त नईलाइन होगी जो इनपुट में नहीं थी।


9

क्यों (पाठ) फाइलें एक नई सीमा के साथ समाप्त होनी चाहिए?

बहुत से लोगों द्वारा व्यक्त किया गया, क्योंकि:

  1. कई कार्यक्रम अच्छा व्यवहार नहीं करते हैं, या इसके बिना विफल हो जाते हैं।

  2. यहां तक ​​कि प्रोग्राम जो अच्छी तरह से एक फ़ाइल को संभालते हैं उनमें एक समाप्ति की कमी होती है '\n', उपकरण की कार्यक्षमता उपयोगकर्ता की अपेक्षाओं को पूरा नहीं कर सकती है - जो इस कोने के मामले में अस्पष्ट हो सकती है।

  3. कार्यक्रम शायद ही कभी अंतिम रूप से अस्वीकार'\n' करते हैं (मुझे किसी का पता नहीं है)।


फिर भी यह अगला प्रश्न बताता है:

एक नई पंक्ति के बिना पाठ फ़ाइलों के बारे में क्या करना चाहिए?

  1. सबसे महत्वपूर्ण - एक कोड फ़ाइल न लिखें जो एक नई फ़ाइल के साथ समाप्त होती हैमान लिया जाये कि डेटा भ्रष्टाचार, हैकर हमलों और दुर्घटनाओं के लिए एक प्रारूप होता है के लिए एक फ़ाइल अनुरूप है। उदाहरण:

    // Bad code
    while (fgets(buf, sizeof buf, instream)) {
      // What happens if there is no \n, buf[] is truncated leading to who knows what
      buf[strlen(buf) - 1] = '\0';  // attempt to rid trailing \n
      ...
    }
    
  2. यदि अंतिम अनुगामी '\n'की आवश्यकता है, तो उपयोगकर्ता को उसकी अनुपस्थिति और की गई कार्रवाई के लिए सतर्क करें। IOWs, फ़ाइल के प्रारूप को मान्य करते हैं। नोट: इसमें अधिकतम लाइन की लंबाई, वर्ण एन्कोडिंग, आदि की एक सीमा शामिल हो सकती है।

  3. स्पष्ट रूप से परिभाषित करें, दस्तावेज़, एक लापता फाइनल के कोड की हैंडलिंग '\n'

  4. , संभव के रूप में, एक फ़ाइल उत्पन्न न होने के कारण समाप्त होता है '\n'


4

यहां बहुत देर हो चुकी है लेकिन मुझे सिर्फ फाइल प्रोसेसिंग में एक बग का सामना करना पड़ा है और वह इसलिए आया क्योंकि फाइलें खाली न्यूलाइन के साथ समाप्त नहीं हो रही थीं। हम sedऔर के साथ पाठ फ़ाइलों को संसाधित कर रहे थेsed आउटपुट से अंतिम पंक्ति को छोड़ जो अमान्य जसन संरचना का कारण बन रही थी और बाकी प्रक्रिया को विफल करने के लिए भेज रही थी।

हम सब कर रहे थे:

एक नमूना फ़ाइल कहती है: इसके अंदर foo.txtकुछ jsonसामग्री के साथ ।

[{
    someProp: value
},
{
    someProp: value
}] <-- No newline here

फ़ाइल को विधवा मशीन में बनाया गया था और विंडो स्क्रिप्ट्स उस फ़ाइल को संसाधित कर रहे थे जो PowerShell कमांड का उपयोग कर रही थी। सब अच्छा।

जब हमने sedकमांड का उपयोग करके उसी फ़ाइल को संसाधित कियाsed 's|value|newValue|g' foo.txt > foo.txt.tmp

नई उत्पन्न फ़ाइल थी

[{
    someProp: value
},
{
    someProp: value

और बूम, यह अमान्य JSON के कारण बाकी प्रक्रियाओं में विफल रहा।

इसलिए अपनी फ़ाइल को खाली नई पंक्ति के साथ समाप्त करना हमेशा एक अच्छा अभ्यास है।


3

मैं हमेशा इस धारणा के अधीन था कि नियम उन दिनों से आया है जब एक फ़ाइल को समाप्त करने के बिना एक नई सीमा पार करना मुश्किल था। यही है, आप लेखन कोड को समाप्त करेंगे जहां लाइन का एक छोर ईओएल चरित्र या ईओएफ द्वारा परिभाषित किया गया था। ईओएल के साथ समाप्त हुई एक लाइन को मान लेना सरल था।

हालाँकि, मेरा मानना ​​है कि नियम सी कंपाइलर से लिया गया है जो नई लाइन की आवश्यकता है। और जैसा कि "फ़ाइल के अंत में कोई नई पंक्ति नहीं" संकलक चेतावनी पर बताया गया है , #include एक नई पंक्ति नहीं जोड़ेगा।


0

कल्पना करें कि फ़ाइल को संसाधित किया जा रहा है, जबकि फ़ाइल अभी भी किसी अन्य प्रक्रिया द्वारा बनाई जा रही है।

इसके साथ क्या करना पड़ सकता है? एक ध्वज जो इंगित करता है कि फ़ाइल संसाधित होने के लिए तैयार है।


-4

मुझे व्यक्तिगत रूप से स्रोत कोड फ़ाइलों के अंत में नई लाइनें पसंद हैं।

इस मामले के लिए लिनक्स या सभी यूनिक्स प्रणालियों के साथ इसका मूल हो सकता है। मुझे याद है कि संकलन त्रुटियां हैं (यदि मुझे गलती नहीं है तो) क्योंकि स्रोत कोड फाइलें एक खाली नई पंक्ति के साथ समाप्त नहीं हुई थीं। क्यों बनाया गया था इस तरह से एक आश्चर्य करने के लिए छोड़ दिया है।


-6

IMHO, यह व्यक्तिगत शैली और राय का विषय है।

पुराने दिनों में, मैंने उस नई पंक्ति को नहीं रखा था। सहेजे गए वर्ण का मतलब उस 14.4K मॉडेम के माध्यम से अधिक गति है।

बाद में, मैंने उस नई लाइन को डाल दिया ताकि शिफ्ट + डाउनरो का उपयोग करके अंतिम पंक्ति का चयन करना आसान हो जाए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.