awk的默认字段分隔符

Lin*_* Ma 20 unix linux awk posix separator

抱歉这个愚蠢的问题,搜索但不自信是找到正确的答案,所以默认的分隔符只是awk的空间?

mkl*_*nt0 21

这是一个适用于所有主要Awk实现实用摘要:

  • GNU awk中(gawk) -默认awk一些 Linux发行版
  • Mawk(mawk) -默认awk一些 Linux发行版(如Ubuntu的)
  • BSD Awk - 又名BWK Awk - awk类似BSD的平台上的默认设置,包括OSX

在Linux上,awk -W version将告诉您默认的实现awk.
BSD awk中理解awk --version(其GNU awk中理解除了awk -W version).

所有这些实现的最新版本遵循关于字段分隔符[1] POSIX标准(但不是记录分隔符).

名词解释:

  • RS输入记录分隔符,它描述输入如何分解为记录:

    • POSIX授权默认值是一个新行,也被称为\n下面; 也就是说,输入默认分为几.
    • awk命令行中,RS可以指定为-v RS=<sep>.
    • POSIX限制RS到一个文字,单字符的值,但GNU awk和Mawk支持多字符可以被值扩展正则表达式(BSD awk并支持).
  • FS输入字段分隔符,它描述了每条记录如何分割成字段 ; 它可能是一个扩展的正则表达式.

    • awk命令行中,FS可以指定为-F <sep>(或-v FS=<sep>).
    • POSIX授权的默认值形式上一个空间(0x20),但空间不是字面解释为(只)分离器,但有特殊的意义 ; 见下文.

默认情况下:

  • 任何运行空间 和/或 突出部和/或换行符被视为字段分隔符
  • 开头和结尾忽略运行.

POSIX规范.使用<blank>空格和制表符的抽象,这适用于所有语言环境,但可能包含特定语言环境中的其他字符 - 我不知道是否存在任何此类语言环境.

需要注意的是使用默认的输入记录分隔符(RS)\n,新行通常不进入图片作为字段分隔符,因为没有记录本身 包含\n在这种情况下.

然而,作为字段分隔符的换行符确实发挥作用:

  • When RS设置为导致记录本身包含\n实例的值(例如when RS设置为空字符串 ;请参阅下文).
  • 通常,当split()函数用于将字符串拆分为数组元素而没有显式字段分隔符参数时.
    • 即使输入记录\n在默认RS有效的情况下也不包含实例,但是在来自不同源split()多行字符串上没有显式字段分隔符参数的情况下调用该函数(例如,通过-v选项传递的变量或伪文件名)始终视为\n字段分隔符.

重要的非默认注意事项:

  • 分配字符串RS具有特殊的意义:它读取输入段落模式,这意味着输入被分成记录的运行非空行,用开头和结尾的忽略空行运行.

  • 当你指定的任何其他不是字面空间FS,该解释FS 的变化从根本上:

    • 单个字符或者从指定的字符的每个字符识别单独作为一个字段分隔符 -不运行它,与默认.
      • 例如,设置FS[ ]- 即使它实际上相当于一个空格 - 会导致每个记录中的每个单独的空间实例都被视为字段分隔符.
      • 要识别运行,+必须使用正则表达式量词(复制符号); 例如,[\t]+将识别标签的运行作为单个分隔符.
    • 不会忽略前导和尾随分隔符,而是将字段分开.
    • 设置FS空字符串意味着记录的每个字符都是其自己的字段.
  • 根据POSIX的要求,如果RS设置为空字符串(段落模式),则newlines(\n)被视为字段分隔符,而不管其值是多少FS.

[1]遗憾的是,当您使用选项强制执行POSIX合规时,至少版本4.1.3的GNU Awk符合关于字段分隔符的过时 POSIX标准,-P(--posix):该选项生效并RS设置为非空值,换行符(\n实例)不会被识别为字段分隔符.GNU Awk手册说明了过时的行为(但忽略了提到当RS设置为字符串时它不适用).POSIX标准在2008年发生了变化(参见注释),当有默认值时,考虑换行字段分隔符FS- 因为GNU Awk总是没有 -P(--posix).
以下是验证上述行为2个命令:
*使用-P在效果和RS设置为空字符串,\n视为字段分隔符:
gawk -P -F' ' -v RS='' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
*使用-P在效果和非空 RS,\n不被视为一个字段分隔符-这是过时的行为:根据GNU Awk维护者的说法,
gawk -P -F' ' -v RS='|' '{ printf "<%s>, <%s>\n", $1, $2 }' <<< $'a\nb'
修复工作即将到来 ; 期望它在版本4.2(没有给出时间框架).
(给@JohnKugelman和@EdMorton提供帮助的帽子提示.)


Ed *_*ton 11

这个问题the default delimiter is only space for awk?很模糊,但我会尽量回答你可能会问的两个问题.

FS变量的默认值(包含告诉awk如何在读取字段时将记录分隔为字段的字段分隔符)是单个空格字符.

awk用于将记录分成字段的东西是"字段分隔符",它是一个带有一些附加功能的正则表达式,仅当字段分隔符是单个空白字符时才适用.该附加功能是:

  1. 在字段拆分期间忽略前导和尾随空格.
  2. 字段由连续的空格字符链分隔,包括空格,制表符和换行符.
  3. 如果要将文字空白字符用作字段分隔符,则必须将其指定为,[ ]而不是像在正则表达式中那样仅使用独立的文字空白字符.

除了用于在读取输入时将记录拆分为字段的字段分隔符之外,它们还用于其他一些上下文中,例如第3个arg用于此split(),因此了解哪些上下文需要字符串或正则表达式或字段搜索以及手册页明确指出了每一个.

除其他外,上面解释了这个:

$ echo ' a b c ' | awk '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F' ' '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F'[ ]' '{printf "%d: <%s> <%s> <%s>\n", NF, $1, $2, $3}'                              
5: <> <a> <b>
Run Code Online (Sandbox Code Playgroud)

所以如果你不明白为什么前2个产生相同的输出但是最后的产生不同,请询问.


Joh*_*ica 8

我们来看看GNU awk手册页:

FS - 输入字段分隔符,默认为空格.见上面的字段.

田野部分!

在读取每个输入记录时,gawk将记录拆分为字段,使用FS变量的值作为字段分隔符.如果FS 是单个字符,则字段由该字符分隔.如果FS是空字符串,则每个单独的字符将成为单独的字段.否则,FS预计将是一个完整的正则表达式.在FS 作为单个空格的特殊情况下 , 字段由空格和/或制表符和/或换行符分隔.