Які умови повинні бути виконані, щоб файл був текстовим файлом, визначеним POSIX?


22

POSIX визначає текстовий файл як:

Файл, який містить символи, впорядковані в нуль або більше рядків. Рядки не містять символів NUL і жодна довжина не може перевищувати {LINE_MAX} байт, включаючи символ <newline>. Хоча POSIX.1-2017 не розрізняє текстові файли та бінарні файли (див. Стандарт ISO C), багато утиліт виробляють передбачуваний або змістовний вихід під час роботи з текстовими файлами. Стандартні утиліти, які мають такі обмеження, завжди вказують "текстові файли" у своїх розділах STDIN або INPUT FILES.

Джерело: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_403

Однак є кілька речей, які мені здаються незрозумілими:

  1. Чи повинен текстовий файл бути звичайним файлом? У наведеному вище уривці прямо не сказано, що файл повинен бути звичайним файлом

  2. Чи може вважатися файлом текстовий файл, якщо він містить лише один символ та один символ (тобто один символ, який не закінчується новим рядком)? Я знаю, що це запитання може здатися непосидючим, але вони використовують слово "символи" замість "один чи більше символів". Інші можуть не погодитися, але якщо вони означають "одного чи декількох символів", я думаю, вони повинні це прямо сказати

  3. У наведеному вище уривку він посилається на "рядки". Я знайшов чотири визначення з рядком у їх назві: "Порожня лінія", "Відображення рядка", "Неповна лінія" та "Рядок". Чи повинен я зробити висновок, що вони означають "Рядок" через те, що вони не мають "Порожня", "Відображення" та "Неповна", - чи всі чотири ці визначення включені як такі, що вважаються рядком у вищевикладеному уривку?

Усі питання, що виникають після цього блоку тексту, залежать від висновку, що "символи" означають "один чи більше символів":

  1. Чи можна сміливо робити висновок, що якщо файл порожній, це не текстовий файл, оскільки він не містить одного або декількох символів?

Усі запитання, що виникають після цього блоку тексту, залежать від висновку, що у наведеному вище уривці рядок визначається як "Рядок", а інші три визначення, що містять "Рядок" у своєму імені, повинні бути виключені:

  1. Чи означає "нуль" у "нульовому чи більше рядках", що файл все ще може вважатися текстовим файлом, якщо він містить один або більше символів, які не закінчуються новим рядком?

  2. Чи означає "нульовий чи більше рядків", що після того, як один гра "Рядок" (0 або більше символів плюс закінчуючий новий рядок) вступає в гру, він стає незаконним, щоб останній рядок був "неповним рядком" (один або більше не- символи нового рядка в кінці файлу)?

  3. Чи "жоден [жоден рядок] не може перевищувати {LINE_MAX} байт у довжину, включаючи символ нового рядка" означає, що в текстовому файлі є обмеження на кількість символів, дозволених у будь-якому заданому "Рядку" (як бік, значення LINE_MAX на Ubuntu 18.04 та FreeBSD 11.1 - "2048")?


Добре запитання, Гарольде! Робить велике обговорення термінології. Бажаю, щоб я міг підкреслити це питання додатково
Сергій Колодяжний,

Відповіді:


23
  1. Чи повинен текстовий файл бути звичайним файлом? У наведеному вище уривці прямо не сказано, що файл повинен бути звичайним файлом

    Ні; уривок навіть спеціально зазначає стандартний ввід як потенційний текстовий файл. Інші стандартні утиліти, такі як make, в зокрема , використовувати в символьний файл /dev/null у вигляді текстового файлу .

  2. Чи може вважатися файлом текстовий файл, якщо він містить лише один символ та один символ (тобто один символ, який не закінчується новим рядком)?

    Цей символ повинен бути <newline>, або це не рядок , і тому файл, в якому знаходиться, не є текстовим файлом. Файл, що містить точно байт 0A, є однорядним текстовим файлом. Порожній рядок - дійсний рядок.

  3. У наведеному вище уривку він посилається на "рядки". Я знайшов чотири визначення з рядком у їх назві: "Порожня лінія", "Відображення рядка", "Неповна лінія" та "Рядок". Я повинен зробити висновок про те, що вони означають "Рядок" через їх упущення "Порожні", "Відображення" та "Неповне"

    Це насправді не умовивід, це просто те, що написано. Слову "рядок" було дано контекстуально відповідне визначення, і ось про що йдеться.

  4. Чи можна сміливо робити висновок, що якщо файл порожній, це не текстовий файл, оскільки він не містить одного або декількох символів?

    Порожній файл складається з нуля (або більше) рядків і, таким чином, є текстовим файлом.

  5. Чи означає "нуль" у "нульовому чи більше рядках", що файл все ще може вважатися текстовим файлом, якщо він містить один або більше символів, які не закінчуються новим рядком?

    Ні, ці символи не впорядковані в рядки.

  6. Чи означає "нульовий чи більше рядків", що після того, як один гра "Рядок" (0 або більше символів плюс закінчуючий новий рядок) вступає в гру, він стає незаконним, щоб останній рядок був "неповним рядком" (один або більше не- символи нового рядка в кінці файлу)?

    Це не незаконно , це просто не текстовий файл. Утиліта, яка вимагає надати їй текстовий файл, може поводитись несприятливо, якщо надати цей файл.

  7. Чи "жоден [жоден рядок] не може перевищувати {LINE_MAX} байт у довжину, включаючи символ нового рядка" означає, що в текстовому файлі є обмеження на кількість символів, дозволених у будь-якому заданому "рядку"

    Так.

Це визначення просто намагається встановити межі того, що текстова утиліта ( наприклад,grep ) напевно прийме - нічого більше. Вони також вільні сприймати речі більш вільно, і досить часто вони це роблять на практиці. Їм дозволено використовувати буфер фіксованого розміру для обробки рядка, припускати, що новий рядок з’являється до його заповнення тощо. Можливо, ви занадто багато читаєте в речі.


1
Ви впевнені в пункті 2? Стандарт чітко вказує " 0 або більше рядків". Так printf "a" > fileбуло б створити текстовий файл відповідно до цього визначення. Ваша відповідь на 4, здається, суперечить вашим відповідям на 2 та 5, оскільки ви припускаєте, що touch fileстворює текстовий файл, а printf "a" > fileні.
тердон

4
@terdon: Я не бачу суперечності у відповіді Майкла. В основному, він, схоже, каже, що текстовий файл POSIX - це будь-який файл, вміст якого відповідає регулярному вираженню (.{0,M}\n)*(неявно закріплений з обох кінців), де \nвідповідає новому рядку і .відповідає будь-якому символу, який не є новим рядком, і Mє заповнювачем числового значення. LINE_MAX-1. Зокрема, це означає, що порожній файл - це дійсний текстовий файл, що складається з нульових рядків, але будь-який непорожній текстовий файл повинен закінчуватися новим рядком (оскільки в іншому випадку він міститиме неповний рядок, а неповний рядок не є рядком ).
Ільмарі Каронен

@Michael Homer Що стосується звичайного файлу, чи є інші приклади, окрім / dev / null? Це насправді не текстовий файл, оскільки він містить один або більше нульових символів.
Гарольд Фішер

1
@HaroldFischer /dev/null- порожній файл. Ти думаєш /dev/zero.
Майкл Гомер

@HaroldFischer, ні, /dev/nullчитається як порожнє, так як у вас немає даних, коли ви їх читаєте. Я не впевнений, що має сенс розглядати тут нерегулярні файли, оскільки багато з них мають динамічний характер. Це включає в себе труби, розетки, пристрої для зарядки, які в основному є лише транспортними інтерфейсами до / від інших об'єктів. Вони не містять статичного набору даних, тому було б більше сенсу розглянути властивості переданих даних, а не властивості файлу .
ilkkachu

7

Як визначено POSIX:

Так, текстовий файл (в основному):

Файл, який містить символи, впорядковані в нуль або більше рядків.

Було б корисно також включити таке визначення:

3.92 Рядок символів

Неперервна послідовність символів, що закінчується першим нульовим байтом і включає його.

3.195 Неповна лінія

Послідовність одного або декількох символів, що не належать <newline>, в кінці файлу.

3.206 Рядок

Послідовність нульових або більше символів, що не належать <newline> плюс закінчуючий символ <newline>.

3.243 Символ нового рядка (<новий рядок>)

Символ, який у вихідному потоці вказує, що друк повинен починатися на початку наступного рядка. Це символ, позначений символом '\ n' мовою C. Не визначено, чи є цей символ точною послідовністю, що передається системою пристрою виводу для здійснення руху до наступного рядка.

3.247 NUL

Символ з усіма бітами, встановленими в нуль.

Зауважте, що "Текстовий файл" не повинен містити балів NUL.


Так:

  1. Чи повинен текстовий файл бути звичайним файлом?
    Ні, цього не потрібно. "Текстовий файл" визначається з точки зору того, що він містить під час читання. Якщо файл містить "нуль або більше рядків", це текстовий файл. Деякий файл, як-от /dev/stdin, може містити текстовий файл, якщо читати його одночасно, а не наступного разу, коли він читається.
  2. Чи можна вважати файл текстовим файлом, якщо він містить лише один символ та один символ…?
    Ні, це неповний рядок (3.195).
    Текстовий файл повинен містити лише неповні рядки.
  3. Я повинен зробити висновок, що вони означають "Лінія" ...?
    Так, слід.
  4. Чи можна сміливо робити висновок, що якщо файл порожній, це не текстовий файл…?
    Ні, порожній файл (нульові символи) - дійсний "текстовий файл".
    Зверху: … нуль або більше рядків… . Нульові рядки (нульові символи) є дійсним "Текстовим файлом".
  5. … Вважається текстовим файлом, якщо він містить один або більше символів, які не закінчуються новим рядком?
    Ні, "неповний рядок" у не (технічно) дійсному "рядку".
  6. Чи означає "нуль" у "нульовому чи більше рядках", що файл все ще може вважатися текстовим файлом, якщо він містить один або більше символів, які не закінчуються новим рядком?
    Ні, неповний рядок - це не "Рядок". Текстовий файл не повинен мати неповні рядки.

  7. … Чи існує обмеження на кількість символів, дозволених у будь-якому заданому рядку в текстовому файлі…?
    Так, не більше {LINE_MAX} байт (на відміну від символів) допускається в будь-якому рядку дійсного "текстового файлу".
    Значення {LINE_MAX} задається у файлі <limit.h>
    (також читається розмір буфера рядка чутливих значень у C? ):

    {LINE_MAX}
    Якщо не зазначено інше, максимальна довжина в байтах рядка введення утиліти (або стандартного вводу, або іншого файлу), коли утиліта описується як обробка текстових файлів. Довжина включає в себе кімната для підтяжки.
    Мінімальне прийнятне значення: {_POSIX2_LINE_MAX}

    Для системи на базі GNU не встановлено обмеження (крім пам'яті) :

    Макрос: int LINE_MAX
    Найбільший текстовий рядок, який можуть підтримувати текстово орієнтовані утиліти POSIX.2. (Якщо ви використовуєте версії GNU цих утиліт, то немає фактичного обмеження, окрім встановленого наявною віртуальною пам'яттю, але немає можливості, щоб бібліотека могла вам це сказати.)

    Здається, це визначено у posix_lim.h2048 році (принаймні для 64-бітових Linux-систем GNU):

    $ grep -ri 'POSIX2_LINE_MAX' /usr/include/ 
    
    /usr/include/x86_64-linux-gnu/bits/xopen_lim.h:#define NL_LANGMAX       _POSIX2_LINE_MAX
    /usr/include/x86_64-linux-gnu/bits/posix2_lim.h:#define _POSIX2_LINE_MAX                2048
    /usr/include/x86_64-linux-gnu/bits/posix2_lim.h:#define LINE_MAX                _POSIX2_LINE_MAX
    

    Він також може бути знайдений за допомогою утиліти POSIX getconf :

    $ getconf LINE_MAX
    2048
    

Пов’язано: Чому текстові файли повинні закінчуватися новим рядком?


2
Ця відповідь здебільшого правильна, але правильної відповіді на тему "чи повинен текстовий файл бути звичайним файлом" - ні . Будь-який тип файлу може бути текстовим файлом, це питання вмісту, тип файлу не має значення. fileУтиліта повідомляє тільки тип файлу для спеціальних файлів, але це тільки як підсобні роботи, використання file - <…або (Linux) , file -s …щоб побачити його евристики на вміст файлу для спеціального файлу. Спеціальний файл може мати різний вміст кожного разу, коли ви відкриваєте його, тому він може бути або бути текстовим файлом кожного разу. /dev/nullце завжди текстовий файл, оскільки його вміст - це завжди текстовий файл.
Жил "ТАК - перестань бути злим"

1
Замість того, щоб використовувати grepдля файлів, ви можете використовувати getconfдля отримання значень конфіденційності системи, наприклад getconf LINE_MAX, що, до речі, повертає 2048 (байти) в моїй системі (Ubuntu 16.04).
heemayl

Я хотів знайти файл, де була визначена змінна, таким чином grep був необхідний, і зробив роботу (досить швидко). Але так, getconfдозволяє читати теперішнє значення config.
Ісаак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.