Metin dosyaları neden bir satırsonu ile bitmelidir?


1468

Buradaki herkesin tüm metin dosyalarının bir satırsonu ile bitmesi gerektiği fikrini bildiklerini düşünüyorum. Yıllardır bu "kuralı" tanıyorum ama hep merak ettim - neden?


30
sadece bir nitpick. dosyanın sonundaki "yeni satır" değil. Son satırın sonunda bir "satır sonu". Ayrıca, ilgili bir soru için en iyi yanıta bakın: stackoverflow.com/questions/16222530/…
gcb

346
Sadece daha fazla nitpick yapmak için, aslında “yeni satır” yazmadı, doğru olan “newline” yazdı.
sindrenm

5
tanıdık değil, ama gerçekten merak ediyorum çünkü bu gereksiz satırsonu aslında şeyleri kırdığı vakaların sayısı
tadıma göre

2
Şu anda düz metin verilerini satır satır ayrıştırmak için Node.js akışlarını kullanıyorum ve akışın giriş tarafı bittiğinde ekstra mantık eklemek zorunda olduğum için terminal satır sonu eksikliği can sıkıcı bir durum. Son satırın işlenmesini sağlamak için kapatıldı.
Mark K Cowan

23
Unix ilişkin yolu aşağıdaki gibi dosyaların sonunda genel davranış şekildedir: \ n karakterleri satırları başlamayın; bunun yerine onları bitiriyorlar. Yani, \ n bir çizgi sonlandırıcıdır, bir çizgi ayırıcı değildir. İlk satırın (tüm satırlar gibi) başlatmak için \ n'ye ihtiyacı yoktur. Son satırın (tüm satırlar gibi) sona erdirmek için \ n gerekir. Dosyanın sonundaki bir \ n ek satır oluşturmaz. Ancak bazen metin editörleri görünür bir boş satır ekler. Emacs bile bunu isteğe bağlı olarak yapar .
MarkDBlackwell

Yanıtlar:


1381

Çünkü POSIX standardı bir hattı şu şekilde tanımlar :

3.206 Hattı
Sıfır veya daha fazla <newline> karakterin yanı sıra sonlandırıcı <newline> karakteri.

Bu nedenle, yeni satır karakteri ile bitmeyen satırlar gerçek satır olarak kabul edilmez. Bu nedenle, bazı programlar, yeni satır sonlandırılmamışsa dosyanın son satırını işlemede sorun yaşar.

Bir terminal emülatörü üzerinde çalışırken bu kılavuzun en az bir zor avantajı vardır: Tüm Unix araçları bu kuralı bekler ve onunla çalışır. Örneğin, dosyaları ile birleştirirken cat, yeni satır tarafından sonlandırılan bir dosya, aşağıdakileri içermeyenden farklı bir etkiye sahip olacaktır:

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

Ve önceki örneğin de gösterdiği gibi, dosyayı komut satırında görüntülerken (örn. Yoluyla more), yeni satır sonlandırılmış bir dosya doğru görüntüyle sonuçlanır. Yanlış sonlandırılmış bir dosya bozuk olabilir (ikinci satır).

Tutarlılık için, bu kurala uymak çok yararlıdır - aksi takdirde varsayılan Unix araçlarıyla uğraşırken ekstra iş yapmanız gerekir.


Başka bir şekilde düşünün: Satırlar satırsonu tarafından sonlandırılmazsa, catyararlı gibi komutlar oluşturmak çok daha zordur: dosyaları birleştirmek için nasıl komut verirsiniz?

  1. her dosyanın başlangıcını yeni bir satıra koyar, bu da zamanın% 95'ini istediğiniz şeydir; fakat
  2. yukarıdaki örnekte olduğu gibi iki dosyanın son ve ilk satırının birleştirilmesini sağlar b.txtve c.txt?

Tabii ki bu çözülebilir, ancak catdaha karmaşık (konumsal komut satırı argümanları ekleyerek) kullanımını yapmanız gerekir cat a.txt --no-newline b.txt c.txtve şimdi her dosya yerine komut diğer dosyalarla nasıl yapıştırılacağını kontrol eder. Bu neredeyse kesinlikle uygun değil.

… Veya sonlandırılmak yerine devam etmesi gereken bir çizgiyi işaretlemek için özel bir sentinel karakteri tanıtmanız gerekir. Şimdi, ters çevrilmiş (satır sonlandırma karakteri yerine satır devamı) dışında POSIX'teki durumla aynı kaldınız.


Şimdi, POSIX uyumlu olmayan sistemlerde (günümüzde çoğunlukla Windows'dur), mesele tartışmalıdır: dosyalar genellikle bir satırsonu ile bitmez ve bir satırın (gayri resmi) tanımı örneğin “ satır satırlarla ayrılmış metin ” olabilir (vurguyu not edin). Bu tamamen geçerlidir. Bununla birlikte, yapılandırılmış veriler için (örn. Programlama kodu) ayrıştırmayı en az karmaşık hale getirir: genellikle ayrıştırıcıların yeniden yazılması gerektiği anlamına gelir. Bir ayrıştırıcı başlangıçta POSIX tanımı göz önünde bulundurularak yazıldıysa, ayrıştırıcıdan ziyade belirteç akışını değiştirmek daha kolay olabilir - başka bir deyişle, girdinin sonuna bir “yapay yeni satır” belirteci ekleyin.


9
Şimdi düzeltmek oldukça pratik olmasa da, POSIX hattı tanımlarken açıkça bir hata yaptı - bu konuyla ilgili soru sayısının kanıtı olarak. Bir satır, <eol>, <eof> veya <eol> <eof> ile sonlandırılmış sıfır veya daha fazla karakter olarak tanımlanmış olmalıdır. Ayrıştırıcı karmaşıklığı geçerli bir endişe değildir. Karmaşıklık, mümkün olan her yerde, programcıların kafasından kütüphaneye taşınmalıdır.
Doug Coburn

23
@DougCoburn Bu cevap, bunun neden yanlış olduğunu ve POSIX'in neden doğru şeyi yaptığını açıklayan kapsamlı, teknik bir tartışmaya sahipti. Maalesef bu yorumlar son zamanlarda aşırı derecede yoğun bir moderatör tarafından silindi. Kısacası, karmaşıklığı ayrıştırmakla ilgili değildir; bunun yerine, tanımınız, cathem kullanışlı hem de tutarlı bir şekilde araç yazmayı çok daha zorlaştırır .
Konrad Rudolph

8
@Leon POSIX kuralı tamamen uç durumları azaltmakla ilgilidir. Ve çok güzel yapıyor. Aslında insanların bunu anlamada başarısız oldukları bir şekilde kayboldum: Bir çizginin mümkün olan en basit, kendi kendine tutarlı tanımı.
Konrad Rudolph

6
@BT Sanırım daha uygun bir iş akışı örneğimin kararın ardındaki neden olduğunu varsayıyorsunuz . Değil, sadece bir sonuç. Bunun nedeni POSIX kuralının en basit ve ayrıştırıcıdaki satırları işlemeyi en kolay hale getiren kural olmasıdır. Tartışmanın bile tek nedeni, Windows'un bunu farklı şekilde yapması ve sonuç olarak POSIX dosyalarında başarısız olan çok sayıda araç olmasıdır. Herkes POSIX yapsaydı, sorun olmazdı. Yine de insanlar POSIX'ten şikayet ediyor, Windows'dan değil.
Konrad Rudolph

7
@BT Yalnızca Windows'a POSIX kurallarının anlamlı olmadığı durumları belirtmek için atıfta bulunuyorum (başka bir deyişle, size bir kemik atıyordum). Bu tartışmada bir daha asla bahsetmekten çok mutluyum. Ancak o zaman iddianız daha az mantıklı: POSIX platformlarında, metin dosyalarını farklı satır sonu sözleşmeleriyle tartışmak hiç mantıklı değil, çünkü bunları üretmek için bir neden yok. Avantajı nedir? Kelimenin tam anlamıyla yok. - Özet olarak, bu cevabın (veya POSIX kuralının) yarattığı nefreti gerçekten anlamıyorum. Açık konuşmak gerekirse, tamamen mantıksız.
Konrad Rudolph

282

Her satır, son satır da dahil olmak üzere yeni satır karakteri ile sonlandırılmalıdır. Bazı programlar, yeni satır sonlandırılmamışsa dosyanın son satırını işlemede sorun yaşar.

GCC , dosyayı işleyemediği için değil , standardın bir parçası olması gerektiği için uyarır .

C dili standardı, boş olmayan bir kaynak dosyasının, hemen ters eğik çizgi karakteri ile başlamaması gereken yeni satır karakteriyle sona ereceğini söylüyor.

Bu bir "irade" cümlesi olduğundan, bu kuralın ihlali için bir teşhis mesajı yayınlamalıyız.

Bu, ANSI C 1989 standardının 2.1.1.2 bölümünde yer almaktadır. ISO C 1999 standardının (ve muhtemelen ISO C 1990 standardının) Bölüm 5.1.1.2'si.

Referans: GCC / GNU posta arşivi .


17
lütfen o zaman ya iş
satırını

4
@BilltheLizard, "Bazı programlar bir dosyanın satır sonlandırılmamışsa son satırını işlemede sorun yaşıyor" bazı örnekleri nelerdir ?
Pacerier

4
@Pacerier wc -l, yeni satır sonlandırılmamışsa dosyanın son satırını saymaz. Ayrıca, catilk dosyanın son satırı yeni satır sonlandırılmamışsa, bir dosyanın son satırını bir sonraki dosyanın ilk satırı ile birleştirir. Sınırlayıcı olarak yeni satırlar arayan hemen hemen her program bunu bozma potansiyeline sahiptir.
Kertenkele Bill

2
@BilltheLizard, ben demek wcolan daha önce de bahsedildiği ....
Pacerier

2
Benim hatam, @BilltheLizard netleştirmek için: sorunları o satır (zaten kitle sözü gibi parçacığı üzerinde olmuştur olanlar dışında sonlandırıldı değilse bir dosyanın son satırını işleme sahip programların bazı örnekler nelerdir catve wc)?
Pacerier

116

Bu cevap, görüşten ziyade teknik bir cevap girişimidir.

POSIX safları olmak istiyorsak, bir satırı şu şekilde tanımlarız:

Sıfır veya daha fazla <newline> karakterin yanı sıra sonlandırıcı <newline> karakteri.

Kaynak: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206

Eksik satır:

Dosyanın sonunda bir veya daha fazla <newline> olmayan karakter dizisi.

Kaynak: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_195

Şu şekilde bir metin dosyası:

Sıfır veya daha fazla satır halinde düzenlenmiş karakterler içeren bir dosya. Satırlar NUL karakter içermez ve hiçbiri <newline> karakteri de dahil olmak üzere {LINE_MAX} bayt uzunluğunu aşamaz. POSIX.1-2008 metin dosyaları ve ikili dosyalar arasında ayrım yapmasa da (ISO C standardına bakın), çoğu yardımcı program metin dosyaları üzerinde çalışırken yalnızca öngörülebilir veya anlamlı çıktı üretir. Bu tür kısıtlamaları olan standart yardımcı programlar, STDIN veya INPUT FILES bölümlerinde her zaman "metin dosyaları" belirtir.

Kaynak: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_397

Aşağıdaki gibi bir dize:

İlk boş bayt tarafından ve bu son bayt dahil sonlandırılmış bir bayt dizisi.

Kaynak: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_396

Bundan sonra, herhangi bir sorunla potansiyel olarak karşılaşacağımız tek zamanın , bir dosya satırı veya bir metin dosyası olarak bir dosya kavramıyla uğraşmamızdır (bir metin dosyasının sıfır organizasyon olması) veya daha fazla satır ve bildiğimiz bir satır <newline> ile sonlanmalıdır).

Tipik bir örnek: wc -l filename.

Gönderen wckılavuzuna okuyoruz:

Satır, <newline> karakteriyle ayrılmış karakter dizesi olarak tanımlanır.

JavaScript, HTML ve CSS dosyalarına metin dosyaları olmalarının etkileri nelerdir?

Tarayıcılarda, modern IDE'lerde ve diğer ön uç uygulamalarında EOF'ta EOL'yi atlamakla ilgili bir sorun yoktur. Uygulamalar dosyaları düzgün şekilde ayrıştırır. Tüm İşletim Sistemleri POSIX standardına uygun olmadığından, dosyaları POSIX standardına (veya herhangi bir OS seviyesi standardına) göre işlemek, işletim sistemi olmayan araçların (örn. Tarayıcılar) pratik olmayacaktır.

Sonuç olarak, bir UNIX işletim sisteminde çalışıyor olsa da, EOF'daki EOL'nin uygulama düzeyinde neredeyse hiçbir olumsuz etkisi olmayacağından emin olabiliriz.

Bu noktada, istemci tarafında JS, HTML, CSS ile uğraşırken EOF'da EOL atlamanın güvenli olduğunu söyleyebiliriz. Aslında, <newline> içermeyen bu dosyalardan herhangi birini küçültmenin güvenli olduğunu belirtebiliriz.

Bunu bir adım öteye taşıyabilir ve NodeJS söz konusu olduğunda, POSIX standardına uygun olarak POSIX uyumlu olmayan ortamlarda çalışabileceğini söyleyebiliriz.

O zaman ne kaldı? Sistem düzeyinde takımlama.

Bu, ortaya çıkabilecek tek sorunların, işlevlerini POSIX'in semantiğine uymaya çalışan araçlarla ilgili olduğu anlamına gelir (örneğin, gösterildiği gibi bir çizginin tanımı wc).

Yine de, tüm mermiler POSIX'e otomatik olarak yapışmaz. Örneğin Bash, POSIX davranışını varsayılan olarak kullanmaz. Etkinleştirmek için bir geçiş vardır: POSIXLY_CORRECT.

EOL'nin <newline> olmasının değeri üzerine düşünülen yiyecekler: https://www.rfc-editor.org/old/EOLstory.txt

Takım pistinde kalmak, tüm pratik amaçlar ve amaçlar için şunu düşünelim:

EOL'si olmayan bir dosyayla çalışalım. Bu yazıda, bu örnekteki dosya EOL içermeyen küçültülmüş bir JavaScript'tir.

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

catDosya boyutunun, tek tek parçalarının toplamı olduğuna dikkat edin . JavaScript dosyalarının birleştirilmesi JS dosyaları için bir endişe kaynağıysa, her JavaScript dosyasını noktalı virgülle başlatmak daha uygun bir sorundur.

Bu iş parçacığında başka birisinin de belirttiği gibi: catçıktısı iki yerine yalnızca bir satır haline gelen iki dosya istiyorsanız ? Başka bir deyişle, catyapması gerekeni yapar.

manArasında catsadece EOF'a girdi okuma bahseder değil, <satır>. -nAnahtarının catayrıca , sayının 1'de ( . ' Ye göre ) başladığı satır olarak, <newline> sonlandırılmamış satırı (veya eksik satırı ) yazdıracağını unutmayın .man

-n 1'den başlayarak çıkış hatlarını numaralandırın.

POSIX'in bir çizgiyi nasıl tanımladığını anladığımıza göre , bu davranış belirsiz veya gerçekten uyumlu değildir.

Belirli bir aracın amacını ve uyumluluğunu anlamak, dosyaları bir EOL ile sonlandırmanın ne kadar kritik olduğunu belirlemeye yardımcı olacaktır. C, C ++, Java (JARs, vb.) 'De bazı standartlar geçerlilik için yeni bir satır belirler - JS, HTML, CSS için böyle bir standart yoktur.

Örneğin, wc -l filenamebirini kullanmak yerine awk '{x++}END{ print x}' filename, görevin başarısının bir dosya tarafından tehlikeye atılmadığından emin olun, yazmadığımızı işlemek isteyebiliriz (örneğin, yaptığımız küçültülmüş JS gibi bir üçüncü taraf kütüphanesi curl) - niyet gerçekten POSIX uyumlu anlamda hatları saymaktı .

Sonuç

JS, HTML ve CSS gibi belirli metin dosyaları için EOF'ta EOL atlamanın olumsuz bir etkisi olacağı çok az gerçek hayat kullanım örneği olacaktır. <newline> 'ın varlığına güvenirsek, takımlarımızın güvenilirliğini yalnızca yazar olduğumuz dosyalarla sınırlandırırız ve kendimizi üçüncü taraf dosyaları tarafından getirilen olası hatalara kadar açarız.

Hikayenin ahlakı: EOF'ta EOL'ye güvenmenin zayıflığı olmayan mühendis araçları.

EOL atlamanın nasıl olumsuz bir etkisi olduğunu inceleyebileceğimiz JS, HTML ve CSS için geçerli oldukları için kullanım durumlarını yayınlamaktan çekinmeyin.


2
POSIX, MVS / OS satır sonlarıyla ilgili ... wat etiketinde değil mi? veya MS-DOS satır sonları? Bu arada, bilinen tüm posix sistemleri son satır sonu olmayan metin dosyalarına izin vermez ("metin dosyasının" çekirdekte özel bir işleme sahip olduğu bir posix uyumlu iddia sistemi bulunmazsa, it)
Luis Colorado

62

Arasındaki farkla ilişkili olabilir :

  • metin dosyası (her satırın bir satır sonu ile bitmesi gerekir)
  • ikili dosya (konuşulacak gerçek bir "satır" yoktur ve dosyanın uzunluğu korunmalıdır)

Her satır bir satır sonu ile bitiyorsa, bu, örneğin, iki metin dosyasını birleştirmenin ilk çalışmanın son satırını ikincinin ilk satırına dönüştürmesini önler.

Ayrıca, bir düzenleyici dosyanın dosyanın bir satır sonu ile bitip bitmediğini, yerel seçenek 'eol' içine kaydedip kaydetmediğini kontrol edebilir ve dosyayı yazarken bunu kullanabilir.

Birkaç yıl önce (2005), birçok editör (ZDE, Eclipse, Scite, ...) çok takdir edilmeyen son EOL'yi "unuttu" .
Sadece bu da değil, son EOL'yi 'yeni bir satır başlat' olarak yanlış yorumladılar ve aslında başka bir satırı zaten varmış gibi göstermeye başladılar.
Bu, yukarıdaki editörlerden birinde açılmaya kıyasla, vim gibi iyi işlenmiş bir metin düzenleyicisine sahip 'uygun' bir metin dosyasıyla çok görünürdü. Dosyanın gerçek son satırının altında fazladan bir satır görüntüledi. Bunun gibi bir şey görüyorsunuz:

1 first line
2 middle line
3 last line
4

11
+1. Bu sorunu yaşarken bu SO sorusunu buldum. Öyle çok bu "sahte" son satırı göstermek için Eclipse can sıkıcı ve bunu kaldırırsanız, o zaman git'e (ve EOL beklediği tüm diğer unix araçları) şikayet ediyor. Ayrıca, bunun sadece 2005'te olmadığını unutmayın: Eclipse 4.2 Juno'nun hala bu sorunu var.
MestreLion


46

Bazı araçlar bunu bekler. Örneğin, şunu wcbekler:

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

22
Ben "bazı" demezdim, diyorum ki çoğu araç hepsi olmasa da metin dosyaları için bunu bekler. cat, git, diff, wc, grep, sed ... liste çok büyük
MestreLion

Belki bir söyleyebiliriz wcgelmez bekliyoruz basitçe "çizgi" nin çoğu insanın sezgisel anlayış yerine bir "çizgi" nin POSIX tanımı içinde çalışmaktadır çok olduğunca bu.
Guildenstern

@Guildenstern Sezgisel tanım her iki durumda da wc -lyazdırmak içindir 1, ancak bazı insanlar ikinci vakanın yazdırılması gerektiğini söyleyebilir 2.
Flimm

@Flimm \nPOSIX / UNIX'in yaptığı gibi, bir çizgi ayırıcı yerine bir çizgi sonlandırıcı olarak düşünüyorsanız , ikinci vakanın 2 yazdırmasını beklemek kesinlikle çılgınca olur.
noktalı virgül

21

Temel olarak, son EOL EOF'u alamazlarsa dosyaları doğru şekilde işlemeyecek birçok program vardır.

GCC sizi bu konuda uyarıyor çünkü C standardının bir parçası olması bekleniyor. (görünüşte bölüm 5.1.1.2)

"Dosya sonunda satırsonu yok" derleyici uyarısı


5
GCC dosyayı işleyemez, C standardının bir parçası olarak uyarı vermek zorundadır.
Bill the Lizard

IIRC, MSVC 2005, eksik satırlarla biten ve muhtemelen bunları derlemeyi reddeden C dosyaları hakkında şikayette bulundu.
Mark K Cowan

16

Bu, basit terminallerin kullanıldığı ilk günlerden kaynaklanmaktadır. Yeni satır, aktarılan verilerin 'yıkanmasını' tetiklemek için kullanıldı.

Bugün, yeni satır karakterleri artık gerekli değil. Elbette, eğer yeni satır orada değilse birçok uygulamanın hala problemleri var, ancak bu uygulamalarda bir hata olduğunu düşünürdüm.

Bununla birlikte , yeni satırın gerekli olduğu bir metin dosyası biçiminiz varsa , basit veri doğrulamayı çok ucuza alırsınız: dosya sonunda satır sonu olmayan bir satırla bitiyorsa, dosyanın bozuk olduğunu bilirsiniz. Her satır için yalnızca bir bayt ile, yüksek doğrulukta ve neredeyse hiç CPU zamanı olmayan bozuk dosyaları algılayabilirsiniz.


15
Bugünlerde için EOF satır metin dosyaları bir gereklilik olmayabilir, ama bir yararlıdır kongre çoğu Unix araçları tutarlı sonuçlarla birlikte çalışmak yapar. Hiç bir hata değil.
MestreLion

14
Birçoğumuz Unix araçlarını hiç kullanmıyoruz ve umursamıyoruz.
DaveWalley

12
Sadece unix araçları değil, herhangi bir araç daha iyi çalışacak ve / veya daha makul dosya formatları varsayabilir.
Sam Watkins

2
@Sam Watkins Basit iyi tanımlanmış biçimlere sahip olmak iyi bir fikirdir . Yine de kodun gerçeğe uygun olması gerekir ve verilerin format uyumlu olduğunu varsaymak gerekmez .
chux - Monica'yı eski haline getirin

8
@MestreLion Bu, aptal standartlara uygun bir dizi kötü araçtan yararsız bir miras . Aşırılıkçı programlamanın bu eserleri (yani her şeyin dosyası! Her şey düz metinle konuşmalıdır!) İcatlarından kısa süre sonra ölmedi çünkü bunlar tarihin belirli bir anında mevcut olan tek araçtı. C, C ++ ile değiştirildi, POSIX'in bir parçası değil, EOF'da EOL gerektirmiyor ve kullanımı * nix luddists tarafından açıkça görülüyor.
polkovnikov.ph

14

Ayrı bir kullanım örneği: metin dosyanız sürüm kontrollü olduğunda (bu durumda, özellikle diğerleri için de geçerli olmasına rağmen özellikle git altında). Dosyanın sonuna içerik eklenirse, daha önce son satır olan satır yeni satır karakteri içerecek şekilde düzenlenmiş olacaktır. Bu blame, o satırın en son ne zaman düzenlendiğini öğrenmek için dosyaya girmenin, gerçekten görmek istediğinizden önce değil, metin eklemesini göstereceği anlamına gelir .


1
diff ve suçlama sadece "newline" ( \n) yerine "new lines" ın tespit edilmesi için güncellenmelidir . Sorun çözüldü.
Andrew

1
Boşluk değişikliklerini yoksaymak için -w etiketini kullanabilirsiniz, ancak bunlar varsayılan değildir.
Robin Whittleton

11

Yukarıdaki pratik nedenlere ek olarak, Unix (Thompson, Ritchie ve diğerleri) veya Multics öncüllerinin yaratıcılarının, hat ayırıcıları kullanmak yerine hat sonlandırıcılarını kullanmanın teorik bir nedeni olduğunu fark etmesi beni şaşırtmaz: sonlandırıcılar, mümkün olan tüm satır dosyalarını kodlayabilirsiniz. Satır ayırıcılarda, sıfır satırlı bir dosya ile tek bir boş satır içeren bir dosya arasında fark yoktur; her ikisi de sıfır karakter içeren bir dosya olarak kodlanır.

Yani nedenleri:

  1. Çünkü POSIX bunu böyle tanımlıyor.
  2. Çünkü bazı araçlar bunu bekler veya onsuz "yanlış davranır". Örneğin,wc -l yeni satırla bitmezse son bir "satır" saymaz.
  3. Çünkü basit ve kullanışlı. Unix'te, catsadece çalışır ve sorunsuz çalışır. Herhangi bir yoruma gerek kalmadan her dosyanın baytını kopyalar. Ben bir DOS eşdeğer olduğunu sanmıyorum cat. Kullanıldığında copy a+b c, son dosya asatırını ilk dosya satırıyla birleştirirsinizb .
  4. Çünkü sıfır satırlı bir dosya (veya akış) bir boş satırlı bir dosyadan ayırt edilebilir.

11

Bunu kendim yıllarca merak ettim. Ama bugün iyi bir nedenle karşılaştım.

Her satırda kaydı olan bir dosya düşünün (ör: CSV dosyası). Ve bilgisayarın dosyanın sonunda kayıtlar yazdığını. Ama aniden çöktü. Gee son çizgiyi tamamladı mı? (hoş bir durum değil)

Ancak her zaman son satırı sonlandırırsak, o zaman bilirdik (sadece son satırın sonlandırılıp sonlandırılmadığını kontrol edin). Aksi takdirde, muhtemelen güvenli olmak için her seferinde son satırı atmamız gerekirdi.


10

Muhtemelen basitçe bazı ayrıştırma kodunun orada olmasını bekliyordu.

Bunu bir "kural" olarak değerlendireceğime emin değilim ve kesinlikle dinsel olarak bağlı olduğum bir şey değil. En mantıklı kod, metnin (kodlamalar dahil) satır satır (herhangi bir satır sonu seçimi), son satırda yeni satırla veya satır satır olmadan nasıl ayrıştırılacağını bilir.

Gerçekten de - yeni bir çizgiyle bitirirseniz: (teoride) EOL ve EOF arasında boş bir son çizgi var mı? Biri düşünmek için ...


12
O kongresi, bir kural değil: Bir çizgi şey olduğunu bir ile biter sonu-of-line . Yani hayır, EOL ve EOF arasında "boş son çizgi" yoktur.
MestreLion

4
@MestreLion: Ancak söz konusu karakter "satır sonu" değil, "satırsonu" ve / veya "satır besleme" olarak adlandırılmıştır. Satır sonlandırıcı değil satır ayırıcı. Ve sonuç son bir boş satır.
Ben Voigt

2
Hiçbir (aklı başında) araç, bir dosyanın son EOL'sini (CR, LF, vb.) Ek, boş bir satır olarak saymaz. Ve biten EOL yoksa, tüm POSIX araçları bir dosyanın son karakterlerini satır olarak saymaz. EOL karakter adının "satır besleme" veya "satır başı" olması fark etmeksizin ("satırsonu" adında bir karakter yoktur), tüm pratik pupalar için duyarlı araçlar satır ayırıcı olarak değil satır sonlandırıcı olarak kabul edilir .
MestreLion

2
@MestreLion, "line terminator" 'un aklı başında olduğundan emin misiniz? Programcı olmayan birkaç kişiyi alın ve hızlı bir anket yapın. Hızlı bir şekilde hat kavramının "hat ayırıcılar" kavramına daha yakın olduğunu fark edeceksiniz . "Hat sonlandırıcı" kavramı sadece garip .
Pacerier

4
@Sahuagin: Bu benim görüşüm değil , POSIX Standardının bir satırı bu şekilde tanımlaması. 0 bayt yer aldığı boş dosya 0 satırları, dolayısıyla hiçbir EOL vardır ve bir dosya sadece tek bir boş satır sahip olarak dikkat edilmesi gereken, bu does bir EOL gerektirir. Ayrıca, bunun yalnızca bir dosyadaki satırları saymak istediğinizde geçerli olduğunu unutmayın , çünkü herhangi bir düzenleyici, zaten bir EOL olup olmadığına bakılmaksızın bir sonraki (veya ilk) satıra "ulaşmanıza" izin verecektir.
MestreLion

10

Sonunda yeni satırları olmayan dosyalarla ilgili pratik bir programlama sorunu da var: readDahili Bash (diğer readuygulamalar hakkında bilmiyorum ) beklendiği gibi çalışmıyor:

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

Bu sadecefoo yazdırılır ! Bunun nedeni, readson satırla karşılaştığında, içindekileri yazar $lineancak EOF'a ulaştığı için çıkış kodu 1'i döndürür. Bu whiledöngüyü kırar , bu yüzden echo $lineparçaya asla ulaşamayız . Bu durumu ele almak istiyorsanız, aşağıdakileri yapmanız gerekir:

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

Yani, dosya sonunda boş olmayan bir satır nedeniyle başarısız echoolursa yapın read. Doğal olarak, bu durumda çıktıda girdi olmayan bir ekstra yeni satır olacaktır.


9

(Metin) dosyaları neden bir satırsonu ile bitmelidir?

Pek çok kişi tarafından ifade edildiği gibi, çünkü:

  1. Birçok program iyi davranmaz veya onsuz başarısız olur.

  2. Bir dosyayı iyi işleyen programların bile sonu yoktur '\n', aracın işlevselliği kullanıcının beklentilerini karşılamayabilir - bu da bu köşe durumunda net olmayabilir.

  3. Programlar nadiren finali yasaklar'\n' (hiçbirini bilmiyorum).


Yine de bu bir sonraki soruya yalvarır:

Yeni satır içermeyen metin dosyaları için kod ne yapmalıdır?

  1. En önemlisi - Bir metin dosyasının yeni satırla bittiği varsayılan kod yazmayın . Varsayarsak veri yolsuzluk, hacker saldırıları ve çöker bir biçim potansiyel müşteriler için bir dosya uygundur. Misal:

    // 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. Son takip '\n'gerekliyse, kullanıcıyı yokluğu ve yapılan işlem konusunda uyarın. IOWs, dosyanın biçimini doğrulayın. Not: Bu, maksimum satır uzunluğu, karakter kodlaması vb. İçin bir sınır içerebilir.

  3. Açıkça tanımlayın, belgeyi, kodun eksik finali ele almasını sağlayın '\n'.

  4. Mümkün olduğunca, sonu olmayan bir dosya oluşturmayın'\n' .


4

Burada çok geç ama ben sadece dosya işleme bir hata ile karşı karşıya ve bu dosyalar boş satırsonu ile bitmedi çünkü geldi. sedVe ile metin dosyalarını işliyorduksed geçersiz json yapısına neden olan ve işlemin geri kalanının başarısız olma durumuna neden olan çıktıdan son satırı çıkarıyorduk.

Tüm yaptığımız şuydu:

Bir örnek dosya var: foo.txtiçinde bazı jsoniçerikler var.

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

Dosya dul makinede oluşturuldu ve pencere komut dosyaları PowerShell komutlarını kullanarak o dosyayı işliyorlardı. Hepsi iyi.

Aynı dosyayı sedkomut kullanarak işlediğimizdesed 's|value|newValue|g' foo.txt > foo.txt.tmp

Yeni oluşturulan dosya

[{
    someProp: value
},
{
    someProp: value

ve boom, geçersiz JSON nedeniyle işlemlerin geri kalanında başarısız oldu.

Bu nedenle, dosyanızı boş yeni satırla bitirmek her zaman iyi bir uygulamadır.


3

Ben her zaman kural son bir satırsonu olmadan bir dosyayı ayrıştırma zor olduğu günlerde geldi izlenimi altındaydı. Yani, satır sonunun EOL karakteri veya EOF tarafından tanımlandığı bir kod yazmanız gerekir. EOL ile biten bir çizgiyi varsaymak daha basitti.

Ancak kuralın satırsonu gerektiren C derleyicilerinden kaynaklandığına inanıyorum. Ve üzerinde sivri out gibi derleyici uyarı “dosya sonunda hiçbir yeni satır” , #include bir yeni satır eklemez.


0

Dosyanın başka bir işlem tarafından oluşturulmaya devam edildiğini düşünün.

Bununla ilgili olabilir mi? Dosyanın işlenmeye hazır olduğunu belirten bir işaret.


-4

Şahsen kaynak kodu dosyalarının sonundaki yeni satırları seviyorum.

Linux ya da tüm UNIX sistemleri ile kökeni olabilir. Kaynak kod dosyaları boş yeni bir satır ile bitmedi çünkü orada derleme hataları (yanılmıyorsam gcc) hatırlıyorum. Neden bu şekilde merak edildi.


-6

IMHO, kişisel bir tarz ve görüş meselesi.

Eski günlerde, o satırsonu koymadım. Kaydedilen bir karakter, 14.4K modemi sayesinde daha fazla hız anlamına gelir.

Daha sonra, bu yeni satırı, shift + downarrow kullanarak son satırı seçmek daha kolay olacak şekilde koydum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.