POSIX definiuje plik tekstowy jako:
Plik zawierający znaki zorganizowane w zero lub więcej wierszy. Wiersze nie zawierają znaków NUL i żaden z nich nie może przekraczać długości {LINE_MAX} bajtów, w tym znaku <nline>. Chociaż POSIX.1-2017 nie rozróżnia plików tekstowych od plików binarnych (patrz standard ISO C), wiele programów narzędziowych generuje przewidywalne lub znaczące wyniki tylko podczas pracy na plikach tekstowych. Standardowe narzędzia, które mają takie ograniczenia, zawsze określają „pliki tekstowe” w swoich sekcjach STDIN lub INPUT FILES.
Źródło: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_403
Jest jednak kilka rzeczy, które są niejasne:
Czy plik tekstowy musi być zwykłym plikiem? W powyższym fragmencie nie jest wyraźnie powiedziane, że plik musi być zwykłym plikiem
Czy plik można uznać za plik tekstowy, jeśli zawiera jeden znak i tylko jeden znak (tj. Pojedynczy znak, który nie jest zakończony znakiem nowej linii)? Wiem, że to pytanie może brzmieć dziwnie, ale używają słowa „znaki” zamiast „jednego lub więcej znaków”. Inni mogą się nie zgadzać, ale jeśli mają na myśli „jedną lub więcej postaci”, myślę, że powinni to wyraźnie powiedzieć
W powyższym fragmencie odnosi się do „linii”. Znalazłem cztery definicje z linią w nazwie: „Pusta linia”, „Wyświetlana linia”, „Niekompletna linia” i „Linia”. Czy mam wnioskować, że mają na myśli „linię” z powodu pominięcia „pustych”, „wyświetlanych” i „niekompletnych” - czy też wszystkie cztery z tych definicji są zawarte jako uważane za wiersz w powyższym fragmencie?
Wszystkie pytania, które pojawiają się po tym bloku tekstu, zależą od wniosku, że „znaki” oznaczają „jeden lub więcej znaków”:
- Czy mogę bezpiecznie wywnioskować, że jeśli plik jest pusty, nie jest to plik tekstowy, ponieważ nie zawiera jednego lub więcej znaków?
Wszystkie pytania, które pojawiają się po tym bloku tekstu, zależą od wywnioskowania, że w powyższym fragmencie wiersz jest zdefiniowany jako „Linia” i że należy wykluczyć pozostałe trzy definicje zawierające „Wiersz” w ich nazwie:
Czy „zero” w „zero lub więcej wierszy” oznacza, że plik nadal można uznać za plik tekstowy, jeśli zawiera jeden lub więcej znaków, które nie są zakończone znakiem nowej linii?
Czy „zero lub więcej linii” oznacza, że po wejściu w grę pojedynczej „linii” (0 lub więcej znaków plus kończąca nowa linia), nielegalne staje się, że ostatnia linia jest „niepełną linią” (jedna lub więcej nieukończonych linii) znaki nowego wiersza na końcu pliku)?
Czy „żaden [brak wiersza] nie może przekraczać długości {LINE_MAX} bajtów, w tym znak nowego wiersza” oznacza, że istnieje ograniczenie liczby znaków dozwolonych w dowolnej „linii” w pliku tekstowym (na marginesie wartość LINE_MAX na Ubuntu 18.04 i FreeBSD 11.1 to „2048”)?
Odpowiedzi:
Nie; fragment nawet zwraca uwagę na standardowe wejście jako potencjalny plik tekstowy. Inne standardowe narzędzia, takie jak
make
, w szczególności wykorzystać ten specjalny plik znakowy/dev/null
postaci pliku tekstowego .Ten znak musi być <nową linią>, w przeciwnym razie nie jest to linia , więc plik, w którym się znajduje, nie jest plikiem tekstowym. Plik zawierający dokładnie bajt 0A to jednowierszowy plik tekstowy. Pusta linia jest prawidłową linią.
To tak naprawdę nie jest wnioskowanie, to po prostu to, co mówi. Słowo „linia” otrzymało odpowiednią kontekstowo definicję, dlatego właśnie o tym mówi.
Pusty plik składa się z zerowych (lub więcej) linii i dlatego jest plikiem tekstowym.
Nie, te znaki nie są zorganizowane w linie.
To nie jest nielegalne , to po prostu plik tekstowy. Narzędzie wymagające podania pliku tekstowego może zachowywać się niekorzystnie, jeśli zamiast tego otrzyma ten plik.
Tak.
Ta definicja próbuje po prostu ustalić pewne granice tego, co narzędzie tekstowe ( na przykład
grep
) na pewno zaakceptuje - nic więcej. Mają też swobodę akceptowania rzeczy bardziej liberalnie i dość często robią to w praktyce. Mogą używać bufora o stałym rozmiarze do przetwarzania linii, aby założyć, że nowa linia pojawia się przed zapełnieniem i tak dalej. Być może za dużo czytasz w rzeczy.źródło
printf "a" > file
plik tekstowy zgodnie z tą definicją. Twoja odpowiedź na 4 wydaje się być sprzeczna z twoimi odpowiedziami na 2 i 5, ponieważ sugerujesz, żetouch file
tworzy plik tekstowy, podczas gdyprintf "a" > file
nie.(.{0,M}\n)*
(domyślnie zakotwiczonym i na obu końcach), w którym\n
pasuje do nowej linii i.
pasuje do dowolnego znaku, który nie jest nową linią, iM
jest symbolem zastępczym dla wartości liczbowej LINE_MAX-1. W szczególności oznacza to, że pusty plik jest prawidłowym plikiem tekstowym składającym się z zerowych linii, ale każdy niepusty plik tekstowy musi kończyć się nową linią (ponieważ w przeciwnym razie zawierałby niekompletną linię, a niekompletna linia nie jest linią )./dev/null
jest pustym plikiem. Myślisz o/dev/zero
./dev/null
czyta jako puste, ponieważ nie dostajesz żadnych danych podczas czytania. Nie jestem pewien, czy warto tutaj uwzględniać nieregularne pliki, ponieważ wiele z nich ma charakter dynamiczny. Dotyczy to rur, gniazd, urządzeń char, które są po prostu transportem interfejsów do / z jakiegoś innego obiektu. Nie przechowują żadnego statycznego zestawu danych, więc rozsądniej byłoby rozważyć właściwości przesłanych danych zamiast właściwości pliku .Zgodnie z definicją POSIX:
Tak, plik tekstowy to (w zasadzie):
Przydatne byłoby również włączenie tych definicji:
3,92 Ciąg znaków
3.195 Niekompletna linia
3,206 linii
3.243 Znak nowej linii (<nowa linia>)
3.247 NUL
Zauważ, że „plik tekstowy” nie może zawierać bajtów NUL.
Więc:
Nie, nie musi tak być. „Plik tekstowy” jest definiowany w kategoriach tego, co zawiera podczas odczytu. Jeśli plik zawiera „zero lub więcej wierszy”, jest to plik tekstowy. Niektóre pliki, na przykład
/dev/stdin
, mogą zawierać plik tekstowy, jeśli zostaną odczytane za jednym razem, a nie następnym razem.Nie, to niepełna linia (3.195).
Plik tekstowy może zawierać tylko „Niekompletne linie”.
Tak, powinieneś.
Nie, pusty plik (zero znaków) jest prawidłowym „plikiem tekstowym”.
Z góry: ... zero lub więcej linii ... . Zero linii (zero znaków) jest prawidłowym „plikiem tekstowym”.
Nie, „Niekompletna linia” nie jest (technicznie) prawidłową „linią”.
Czy „zero” w „zero lub więcej wierszy” oznacza, że plik nadal można uznać za plik tekstowy, jeśli zawiera jeden lub więcej znaków, które nie są zakończone znakiem nowej linii?
Nie, niepełna linia nie jest „linią”. Plik tekstowy nie może zawierać niekompletnych wierszy.
… Istnieje ograniczenie liczby znaków dozwolonych w dowolnej „linii” w pliku tekstowym…?
Tak, nie może być więcej niż {LINE_MAX} bajtów (w przeciwieństwie do znaków) w dowolnym wierszu prawidłowego „pliku tekstowego”.
Wartość {LINE_MAX} jest podana w pliku <limit.h>
(czytaj także Rozsądny rozmiar bufora linii w C? ):
W przypadku systemu opartego na GNU nie ma ustalonego limitu (oprócz pamięci) :
Wygląda na to,
posix_lim.h
że jest to 2048 (przynajmniej dla 64-bitowych systemów GNU Linux):Można go również znaleźć za pomocą narzędzia getconf POSIX :
Powiązane: Dlaczego pliki tekstowe powinny kończyć się nową linią?
źródło
file
Narzędzie zgłasza tylko typ pliku dla plików specjalnych, ale to tylko jak prace użytkowych, użyciefile - <…
lub (Linux)file -s …
, aby zobaczyć jego heurystyki na zawartości pliku na specjalnym pliku. Plik specjalny może mieć różną zawartość za każdym razem, gdy go otwierasz, więc może być plikiem tekstowym za każdym razem./dev/null
jest zawsze plikiem tekstowym, ponieważ jego zawartość jest zawsze plikiem tekstowym.grep
na plikach, możesz użyć,getconf
aby uzyskać systemowe wartości konf, np.getconf LINE_MAX
Które przy okazji zwracają 2048 (bajtów) w moim systemie (Ubuntu 16.04).getconf
pozwala odczytać aktualną wartość config.