मुझे लगता है कि यहां हर कोई इस कहावत से परिचित है कि सभी पाठ फाइलें एक नई पंक्ति के साथ समाप्त होनी चाहिए। मैंने वर्षों से इस "नियम" के बारे में जाना है लेकिन मुझे हमेशा आश्चर्य होता है - क्यों?
मुझे लगता है कि यहां हर कोई इस कहावत से परिचित है कि सभी पाठ फाइलें एक नई पंक्ति के साथ समाप्त होनी चाहिए। मैंने वर्षों से इस "नियम" के बारे में जाना है लेकिन मुझे हमेशा आश्चर्य होता है - क्यों?
जवाबों:
क्योंकि 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
उपयोगी बनाना बहुत कठिन है: आप फ़ाइलों को संक्षिप्त करने के लिए एक कमांड कैसे बनाते हैं
b.txt
और नीचे के उदाहरण में है c.txt
?बेशक यह हल करने योग्य है, लेकिन आपको cat
अधिक जटिल का उपयोग करने की जरूरत है (स्थितीय कमांड लाइन तर्क जोड़कर, उदाहरण के लिए cat a.txt --no-newline b.txt c.txt
), और अब प्रत्येक व्यक्तिगत फ़ाइल के बजाय कमांड यह नियंत्रित करता है कि इसे अन्य फ़ाइलों के साथ कैसे चिपकाया जाता है। यह लगभग निश्चित रूप से सुविधाजनक नहीं है।
… या आपको एक पंक्ति को चिह्नित करने के लिए एक विशेष प्रहरी वर्ण शुरू करने की आवश्यकता है जिसे समाप्त करने के बजाय जारी रखना चाहिए। ठीक है, अब आप POSIX पर उसी स्थिति के साथ फंस गए हैं, सिवाय उलटे (लाइन समाप्ति वर्ण के बजाय लाइन निरंतरता)।
अब, गैर POSIX आज्ञाकारी प्रणालियों पर (आजकल जो कि ज्यादातर विंडोज है), बिंदु मूट है: फाइलें आम तौर पर एक नई पंक्ति के साथ समाप्त नहीं होती हैं, और उदाहरण के लिए एक पंक्ति की (अनौपचारिक) परिभाषा "पाठ जो newlines द्वारा अलग की जाती है" हो सकती है (जोर पर ध्यान दें)। यह पूरी तरह से वैध है। हालांकि, संरचित डेटा (जैसे प्रोग्रामिंग कोड) के लिए यह पार्सिंग को न्यूनतम रूप से अधिक जटिल बनाता है: इसका आमतौर पर मतलब है कि पार्सर्स को फिर से लिखना होगा। यदि कोई पार्सर मूल रूप से पॉसिक्स परिभाषा को ध्यान में रखकर लिखा गया था, तो हो सकता है कि पार्सर के बजाय टोकन स्ट्रीम को संशोधित करना आसान हो - दूसरे शब्दों में, इनपुट के अंत में एक "कृत्रिम नई लाइन" टोकन जोड़ें।
cat
कि यह उपयोगी और सुसंगत दोनों है।
प्रत्येक पंक्ति को एक नए वर्ण में समाप्त किया जाना चाहिए, जिसमें अंतिम एक भी शामिल है। कुछ प्रोग्राम में फ़ाइल की अंतिम पंक्ति को संसाधित करने में समस्याएँ होती हैं, यदि यह नई पंक्तिबद्ध नहीं है।
क्योंकि यह जीसीसी नहीं इसके बारे में चेतावनी दी है नहीं कर सकते हैं फ़ाइल पर कार्रवाई, लेकिन क्योंकि यह करना पड़ता है मानक के हिस्से के रूप।
C भाषा मानक कहता है कि एक स्रोत फ़ाइल जो खाली नहीं है, एक नई-पंक्ति वर्ण में समाप्त हो जाएगी, जो तुरंत बैकस्लैश वर्ण से पहले नहीं होगी।
चूंकि यह "करेगा" खंड है, इसलिए हमें इस नियम के उल्लंघन के लिए एक नैदानिक संदेश का उत्सर्जन करना चाहिए।
यह ANSI C 1989 मानक के खंड 2.1.1.2 में है। आईएसओ सी 1999 मानक की धारा 5.1.1.2 (और शायद आईएसओ सी 1990 मानक भी)।
संदर्भ: GCC / GNU मेल संग्रह ।
wc -l
एक फ़ाइल की अंतिम पंक्ति की गणना नहीं करेगा यदि यह नई पंक्तिबद्ध नहीं है। इसके अलावा, cat
अगली फ़ाइल की पहली पंक्ति के साथ एक फ़ाइल की अंतिम पंक्ति में शामिल हो जाएगा अगर पहली फ़ाइल की अंतिम पंक्ति को नई पंक्तिबद्ध नहीं किया गया है। बहुत ज्यादा है कि किसी भी कार्यक्रम के रूप में नए सिरे से खोज रहा है एक अपराधी के रूप में यह गड़बड़ करने की क्षमता है।
wc
कि पहले ही उल्लेख किया गया है ....
cat
और wc
?
यह उत्तर राय के बजाय तकनीकी उत्तर का प्रयास है।
यदि हम 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> पर भरोसा करते हैं, तो हम अपनी टूलिंग की विश्वसनीयता को केवल उन फ़ाइलों तक सीमित कर रहे हैं, जिन्हें हम लेखक और तीसरे पक्ष की फाइलों द्वारा शुरू की गई संभावित त्रुटियों तक खोलते हैं।
कहानी का नैतिक: इंजीनियर टूलिंग जिसमें ईओएल पर ईओएल पर भरोसा करने की कमजोरी नहीं है।
जेएस, एचटीएमएल और सीएसएस पर लागू होने के बाद उपयोग के मामलों को बेझिझक करें जहां हम जांच कर सकते हैं कि ईओएल को कैसे छोड़ना एक प्रतिकूल प्रभाव है।
यह बीच के अंतर से संबंधित हो सकता है :
यदि प्रत्येक पंक्ति अंत-पंक्ति में समाप्त होती है, तो यह टालता है, उदाहरण के लिए, दो पाठ फ़ाइलों को संक्षिप्त करने से पहली पंक्ति की अंतिम पंक्ति दूसरी पंक्ति में पहली पंक्ति में आ जाएगी।
साथ ही, एक संपादक लोड की जांच कर सकता है कि क्या फ़ाइल एंड-ऑफ़-लाइन में समाप्त होती है, इसे अपने स्थानीय विकल्प 'ईओएल' में बचाता है, और फ़ाइल लिखते समय इसका उपयोग करता है।
कुछ साल पहले (2005), कई संपादकों (ZDE, Eclipse, Scite, ...) ने उस अंतिम ईओएल को "भूल" किया, जो बहुत सराहा नहीं गया था ।
इतना ही नहीं, लेकिन उन्होंने उस अंतिम ईओएल को गलत तरीके से व्याख्या किया, जैसा कि 'एक नई लाइन शुरू करें', और वास्तव में एक और लाइन प्रदर्शित करना शुरू कर देता है जैसे कि यह पहले से मौजूद है।
यह उपरोक्त संपादकों में से एक को खोलने की तुलना में विम जैसे एक अच्छी तरह से व्यवहार किए गए पाठ संपादक के साथ एक 'उचित' टेक्स्ट फ़ाइल के साथ बहुत ही स्पष्ट था। यह फ़ाइल की वास्तविक अंतिम पंक्ति के नीचे एक अतिरिक्त रेखा प्रदर्शित करता है। आप कुछ इस तरह देखते हैं:
1 first line
2 middle line
3 last line
4
कुछ उपकरण इसकी उम्मीद करते हैं। उदाहरण के लिए, wc
यह अपेक्षा करता है:
$ echo -n "Line not ending in a new line" | wc -l
0
$ echo "Line ending with a new line" | wc -l
1
wc
यह उम्मीद नहीं करता है , जितना कि यह "लाइन" के पॉज़िक्स परिभाषा के भीतर काम कर रहा है, जैसा कि "लाइन" के अधिकांश लोगों की सहज समझ के विपरीत है।
wc -l
मुद्रित करने के लिए होगी 1
, लेकिन कुछ लोग कह सकते हैं कि दूसरे मामले को प्रिंट करना चाहिए 2
।
\n
एक लाइन टर्मिनेटर के रूप में सोचते हैं , बल्कि एक लाइन विभाजक के रूप में, जैसा कि POSIX / UNIX करता है, तो 2 प्रिंट करने के लिए दूसरे मामले की अपेक्षा करना बिल्कुल पागल है।
मूल रूप से ऐसे कई कार्यक्रम हैं जो अंतिम ईओएल ईओएफ नहीं मिलने पर फाइलों को सही ढंग से संसाधित नहीं करेंगे।
जीसीसी आपको इस बारे में चेतावनी देता है क्योंकि यह सी मानक के हिस्से के रूप में अपेक्षित है। (खंड 5.1.1.2 जाहिरा तौर पर)
यह शुरुआती दिनों से शुरू होता है जब सरल टर्मिनलों का उपयोग किया जाता था। नईलाइन चार्ट का उपयोग स्थानांतरित डेटा के 'फ्लश' को ट्रिगर करने के लिए किया गया था।
आज, नई लाइन चार की आवश्यकता नहीं है। निश्चित रूप से, यदि नयालाइन नहीं है, तो कई ऐप्स को अभी भी समस्या है, लेकिन मैं उन ऐप्स में बग पर विचार करूंगा।
यदि आपके पास एक पाठ फ़ाइल प्रारूप है जहाँ आपको नई लाइन की आवश्यकता होती है, तो आपको सरल डेटा सत्यापन बहुत सस्ता मिलता है: यदि फ़ाइल एक पंक्ति के साथ समाप्त होती है जिसमें अंत में कोई नई रेखा नहीं है, तो आप जानते हैं कि फ़ाइल टूट गई है। प्रत्येक पंक्ति के लिए केवल एक अतिरिक्त बाइट के साथ, आप उच्च सटीकता और लगभग कोई सीपीयू समय के साथ टूटी हुई फ़ाइलों का पता लगा सकते हैं।
एक अलग उपयोग का मामला: जब आपकी पाठ फ़ाइल संस्करण नियंत्रित होती है (विशेष रूप से इस मामले में, हालांकि यह दूसरों पर भी लागू होती है)। यदि सामग्री को फ़ाइल के अंत में जोड़ा जाता है, तो जो लाइन पहले अंतिम पंक्ति थी, उसे एक नई लाइन वर्ण शामिल करने के लिए संपादित किया जाएगा। इसका मतलब यह है कि blame
फ़ाइल को यह पता लगाने के लिए कि उस पंक्ति को अंतिम बार कब संपादित किया गया था, पाठ जोड़ दिखाएगा, न कि इससे पहले कि आप वास्तव में देखना चाहते थे।
\n
) के बजाय "नई पंक्तियों" का पता लगाने के लिए अंतर और दोष को अद्यतन किया जाना चाहिए । समस्या सुलझ गयी।
उपरोक्त व्यावहारिक कारणों के अलावा, यदि यूनिक्स (थॉम्पसन, रिची, एट अल।) या उनके मल्टिक्स पूर्ववर्तियों के प्रवर्तकों ने महसूस किया कि लाइन विभाजक के बजाय लाइन टर्मिनेटर का उपयोग करने का एक सैद्धांतिक कारण है तो यह मुझे आश्चर्यचकित नहीं करेगा। टर्मिनेटर, आप लाइनों की सभी संभव फ़ाइलों को सांकेतिक शब्दों में बदलना कर सकते हैं। लाइन विभाजकों के साथ, शून्य लाइनों की फाइल और सिंगल खाली लाइन वाली फाइल में कोई अंतर नहीं है; वे दोनों शून्य वर्ण वाली फ़ाइल के रूप में एन्कोडेड हैं।
तो, कारण हैं:
wc -l
एक अंतिम "लाइन" नहीं गिना जाएगा यदि यह एक नई रेखा के साथ समाप्त नहीं होता है।cat
बस काम करता है और यह जटिलता के बिना काम करता है। यह सिर्फ व्याख्या के लिए किसी भी आवश्यकता के बिना, प्रत्येक फ़ाइल के बाइट्स को कॉपी करता है। मुझे नहीं लगता कि इसके बराबर कोई डॉस है cat
। उपयोग copy a+b c
करने से फ़ाइल a
की पहली पंक्ति के साथ फ़ाइल की अंतिम पंक्ति का विलय हो जाएगाb
।मैंने वर्षों से खुद को आश्चर्यचकित किया है। लेकिन मैं आज एक अच्छे कारण के साथ आया हूं।
हर लाइन पर रिकॉर्ड के साथ फाइल की कल्पना करें (उदा: CSV फ़ाइल)। और यह कि कंप्यूटर फ़ाइल के अंत में रिकॉर्ड लिख रहा था। लेकिन यह अचानक दुर्घटनाग्रस्त हो गया। Gee अंतिम पंक्ति थी? (अच्छी स्थिति नहीं)
लेकिन अगर हम हमेशा अंतिम पंक्ति को समाप्त करते हैं, तो हमें पता होगा (बस अंतिम पंक्ति समाप्त होने पर जांच लें)। अन्यथा हमें शायद हर बार अंतिम पंक्ति को त्यागना होगा, बस सुरक्षित रहने के लिए।
मुमकिन है कि कुछ पार्सिंग कोड की उम्मीद है कि यह वहाँ होगा।
मुझे यकीन नहीं है कि मैं इसे "नियम" मानूंगा, और यह निश्चित रूप से ऐसा कुछ नहीं है जिसे मैं धार्मिक रूप से मानता हूं। अधिकांश समझदार कोड को पता होगा कि पाठ को कैसे पार्स करना है (एन्कोडिंग सहित) लाइन-बाय-लाइन (लाइन एंडिंग का कोई विकल्प), अंतिम पंक्ति पर एक नई रेखा के साथ या बिना।
वास्तव में - यदि आप एक नई रेखा के साथ समाप्त होते हैं: क्या ईओएल और ईओएफ के बीच एक खाली अंतिम रेखा है? एक से विचार करना ...
अंत में 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
फ़ाइल के अंत में एक गैर-रिक्त रेखा के कारण विफल हुआ है। स्वाभाविक रूप से, इस मामले में आउटपुट में एक अतिरिक्त नईलाइन होगी जो इनपुट में नहीं थी।
क्यों (पाठ) फाइलें एक नई सीमा के साथ समाप्त होनी चाहिए?
बहुत से लोगों द्वारा व्यक्त किया गया, क्योंकि:
कई कार्यक्रम अच्छा व्यवहार नहीं करते हैं, या इसके बिना विफल हो जाते हैं।
यहां तक कि प्रोग्राम जो अच्छी तरह से एक फ़ाइल को संभालते हैं उनमें एक समाप्ति की कमी होती है '\n'
, उपकरण की कार्यक्षमता उपयोगकर्ता की अपेक्षाओं को पूरा नहीं कर सकती है - जो इस कोने के मामले में अस्पष्ट हो सकती है।
कार्यक्रम शायद ही कभी अंतिम रूप से अस्वीकार'\n'
करते हैं (मुझे किसी का पता नहीं है)।
फिर भी यह अगला प्रश्न बताता है:
एक नई पंक्ति के बिना पाठ फ़ाइलों के बारे में क्या करना चाहिए?
सबसे महत्वपूर्ण - एक कोड फ़ाइल न लिखें जो एक नई फ़ाइल के साथ समाप्त होती है । मान लिया जाये कि डेटा भ्रष्टाचार, हैकर हमलों और दुर्घटनाओं के लिए एक प्रारूप होता है के लिए एक फ़ाइल अनुरूप है। उदाहरण:
// 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
...
}
यदि अंतिम अनुगामी '\n'
की आवश्यकता है, तो उपयोगकर्ता को उसकी अनुपस्थिति और की गई कार्रवाई के लिए सतर्क करें। IOWs, फ़ाइल के प्रारूप को मान्य करते हैं। नोट: इसमें अधिकतम लाइन की लंबाई, वर्ण एन्कोडिंग, आदि की एक सीमा शामिल हो सकती है।
स्पष्ट रूप से परिभाषित करें, दस्तावेज़, एक लापता फाइनल के कोड की हैंडलिंग '\n'
।
, संभव के रूप में, एक फ़ाइल उत्पन्न न होने के कारण समाप्त होता है '\n'
।
यहां बहुत देर हो चुकी है लेकिन मुझे सिर्फ फाइल प्रोसेसिंग में एक बग का सामना करना पड़ा है और वह इसलिए आया क्योंकि फाइलें खाली न्यूलाइन के साथ समाप्त नहीं हो रही थीं। हम 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 के कारण बाकी प्रक्रियाओं में विफल रहा।
इसलिए अपनी फ़ाइल को खाली नई पंक्ति के साथ समाप्त करना हमेशा एक अच्छा अभ्यास है।
मैं हमेशा इस धारणा के अधीन था कि नियम उन दिनों से आया है जब एक फ़ाइल को समाप्त करने के बिना एक नई सीमा पार करना मुश्किल था। यही है, आप लेखन कोड को समाप्त करेंगे जहां लाइन का एक छोर ईओएल चरित्र या ईओएफ द्वारा परिभाषित किया गया था। ईओएल के साथ समाप्त हुई एक लाइन को मान लेना सरल था।
हालाँकि, मेरा मानना है कि नियम सी कंपाइलर से लिया गया है जो नई लाइन की आवश्यकता है। और जैसा कि "फ़ाइल के अंत में कोई नई पंक्ति नहीं" संकलक चेतावनी पर बताया गया है , #include एक नई पंक्ति नहीं जोड़ेगा।
कल्पना करें कि फ़ाइल को संसाधित किया जा रहा है, जबकि फ़ाइल अभी भी किसी अन्य प्रक्रिया द्वारा बनाई जा रही है।
इसके साथ क्या करना पड़ सकता है? एक ध्वज जो इंगित करता है कि फ़ाइल संसाधित होने के लिए तैयार है।
मुझे व्यक्तिगत रूप से स्रोत कोड फ़ाइलों के अंत में नई लाइनें पसंद हैं।
इस मामले के लिए लिनक्स या सभी यूनिक्स प्रणालियों के साथ इसका मूल हो सकता है। मुझे याद है कि संकलन त्रुटियां हैं (यदि मुझे गलती नहीं है तो) क्योंकि स्रोत कोड फाइलें एक खाली नई पंक्ति के साथ समाप्त नहीं हुई थीं। क्यों बनाया गया था इस तरह से एक आश्चर्य करने के लिए छोड़ दिया है।
IMHO, यह व्यक्तिगत शैली और राय का विषय है।
पुराने दिनों में, मैंने उस नई पंक्ति को नहीं रखा था। सहेजे गए वर्ण का मतलब उस 14.4K मॉडेम के माध्यम से अधिक गति है।
बाद में, मैंने उस नई लाइन को डाल दिया ताकि शिफ्ट + डाउनरो का उपयोग करके अंतिम पंक्ति का चयन करना आसान हो जाए।