要使文件成为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}个字节,包括换行符”是否表示文本文件中任何给定“行”中允许的字符数有限制(顺便说一句,在Ubuntu 18.04和FreeBSD 11.1上的LINE_MAX是“ 2048”)吗?


好问题,哈罗德!引起了术语的极大讨论。希望我能多次
投票赞成

Answers:


23
  1. 文本文件必须是常规文件吗?在上面的摘录中,它没有明确指出文件必须是常规文件

    没有; 摘录甚至专门将标准输入记录为潜在的文本文件。其他的标准工具,比如 make专门使用字符特殊文件 /dev/null 为文本文件

  2. 如果文件仅包含一个字符和一个字符(即,一个不以换行符终止的字符),可以将其视为文本文件吗?

    该字符必须是<newline>,或者不是line,因此它所在的文件不是文本文件。正好包含字节0A的文件是单行文本文件。空行是有效行。

  3. 在上面的摘录中,它引用了“线条”。我在名称中找到了四个带有行的定义:“空行”,“显示行”,“不完整行”和“行”。我是否应该推断出它们的意思是“行”,因为省略了“空”,“显示”和“不完整”

    这不是一个真正的推论,而是它所说的。字“行”已被赋予了上下文,恰当的定义,因此,这就是它的谈论。

  4. 我可以安全地推断出,如果一个文件为空,则它不是文本文件,因为它不包含一个或多个字符?

    空文件由零(或更多)行组成,因此是文本文件。

  5. “零个或多个行”中的“零”是否意味着如果文件包含一个或多个未以换行符终止的字符,仍可以将其视为文本文件?

    不,这些字符没有组织成行。

  6. “零行或更多行”是否表示一旦出现一个“行”(0个或多个字符加上一个换行符),则最后一行成为“不完整行”(一个或多个非文件末尾的换行符)?

    这不是非法的,它不是文本文件。如果给定一个文本文件,则需要向其提供文本文件的实用程序可能会产生不利影响。

  7. “ [没有行]的长度不能超过{LINE_MAX}个字节,包括换行符”是否表示文本文件中任何给定“行”中允许的字符数有限制

    是。

此定义只是试图为基于文本的实用程序(例如grep)肯定会接受的内容设置一些界限,仅此而已。他们还可以自由地接受更自由的事情,而且他们经常在实践中接受。允许他们使用固定大小的缓冲区来处理一行,并假定换行符在行满之前就出现了,依此类推。您可能对事物了解过多。


1
您确定要点2吗?该标准明确规定“ 0条或更多行”。因此,printf "a" > file将根据该定义创建一个文本文件。您对4的答案似乎与对2和5的答案相矛盾,因为您建议touch file创建一个文本文件,而printf "a" > file不必。
terdon

4
@terdon:我看不出迈克尔的回答有任何矛盾之处。基本上,他似乎是说POSIX文本文件是其内容与regexp (.{0,M}\n)*(隐式锚定并且两端均\n匹配),匹配换行符并.匹配任何非换行符且M是数字占位符的任何文件。 LINE_MAX-1。特别是,这意味着空文件是由零行组成的有效文本文件,但是任何非空文本文件都必须以换行符结尾(因为否则它将包含不完整的行,并且不完整的行不是行) )。
Ilmari Karonen

@Michael Homer关于常规文件,除/ dev / null外还有其他示例吗?它实际上不是文本文件,因为它包含一个或多个空字符。
哈罗德·菲舍尔

1
@HaroldFischer /dev/null是一个空文件。您正在考虑/dev/zero
迈克尔·荷马,

@HaroldFischer,不,/dev/null读取为空,因为读取时没有任何数据。我不确定在这里考虑非常规文件是否有意义,因为其中许多都是动态的。这包括管道,套接字,char设备,它们基本上只是与其他实体之间的传输接口。它们不保存任何静态数据集,因此考虑传输的数据的属性而不是文件的属性更有意义。
ilkkachu

7

根据POSIX的定义:

是的,一个文本文件(基本上)是:

包含以零行或更多行组织的字符的文件。

包含以下定义将很有用:

3.92字符串

由第一个空字节(包括第一个空字节)终止的连续字符序列。

3.195不完整的线

文件末尾的一个或多个非<newline>字符序列。

3.206线

零个或多个非<newline>字符加上终止的<newline>字符的序列。

3.243换行符(<newline>)

输出流中的一个字符表示应从下一行的开头开始打印。它是用C语言中的'\ n'指定的字符。尚不确定该字符是否是系统传输到输出设备以完成到下一行的准确序列。

3.247无

所有位都设置为零的字符。

请注意,“文本文件”将包含NUL字节。


所以:

  1. 文本文件必须是常规文件吗?
    不,不需要。“文本文件”是根据读取时所包含的内容来定义的。如果文件包含“零行或更多行”,则为文本文件。某些文件(例如)/dev/stdin如果一次读取而不是在下次读取时可能包含一个文本文件。
  2. 如果文件仅包含一个字符和一个字符,可以将其视为文本文件吗?
    不,这是一条不完整的行(3.195)。
    文本文件应仅包含非“不完整的行”。
  3. 我是否应该推断出它们的意思是“线”……?
    是的你应该。
  4. 我可以安全地推断出,如果文件为空,则不是文本文件……?
    不,空文件(零个字符)是有效的“文本文件”。
    从上方开始:…零行或更多行…。零行(零字符)是有效的“文本文件”。
  5. …如果一个文本文件包含一个或多个未以换行符终止的字符,则认为该文本文件?
    不,“不完整的行”不是(技术上)有效的“行”。
  6. “零个或多个行”中的“零”是否意味着如果文件包含一个或多个未以换行符终止的字符,仍可以将其视为文本文件?
    不,不完整的行不是“行”。一个文本文件,将不会有不完整的线。

  7. …对文本文件中任何给定“行”中允许的字符数有限制……?
    是的,在有效的“文本文件”的任何给定行中,不得超过{LINE_MAX} 个字节(相对于字符)。
    {LINE_MAX}的值在文件<limits.h>中给出
    (也读取C中的明智行缓冲区大小):

    {LINE_MAX}
    除非另有说明,否则当实用程序被描述为处理文本文件时,该实用程序的输入行(标准输入或另一个文件)的最大长度(以字节为单位)。长度包括尾随的空间。
    最低可接受值:{_ POSIX2_LINE_MAX}

    对于基于GNU的系统,没有设置限制(内存除外)

    宏:int LINE_MAX
    面向文本的POSIX.2实用程序可以支持的最大文本行。(如果使用的是这些实用程序的GNU版本,那么除了可用虚拟内存所施加的限制外,没有其他实际限制,但是库无法告诉您这一点。)

    它似乎定义 posix_lim.h为2048(至少对于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始终是文本文件,因为其内容始终是文本文件。
吉尔斯(Gillles)“所以-别再作恶了”

1
grep您可以使用而不是在文件上使用getconf来获取系统conf值,例如getconf LINE_MAX,该值在我的系统上会返回2048(字节)(Ubuntu 16.04)。
heemayl

我想找到定义了变量的文件,因此grep是必需的,并且做得很好(很快)。但是可以,getconf允许读取config的当前值。
以撒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.