awk 的默认字段分隔符

2024-11-14 08:30:00
admin
原创
20
摘要:问题描述:awk 的默认分隔符只有空格吗?解决方案 1:以下是适用于所有主要 Awk 实现的实用摘要:GNU Awk ( ) -一些Linux 发行版中的gawk默认设置awkMawk( )-某些Linux 发行版中的mawk默认设置(例如,早期版本的 Ubuntu crysman报告称 19.04 版本现在...

问题描述:

awk 的默认分隔符只有空格吗?


解决方案 1:

以下是适用于所有主要 Awk 实现的实用摘要

  • GNU Awk ( ) -一些Linux 发行版中的gawk默认设置awk

  • Mawk( )-某些Linux 发行版中的mawk默认设置(例如,早期版本的 Ubuntu crysman报告称 19.04 版本现在附带GNU Awk - 请参阅下面的评论。)awk

  • BWKawk Awk -类 BSD 平台(包括 macOS)的默认设置

在 Linux 上,awk -W version将告诉您默认的实现awk是哪种。Awk理解

BWK (GNU Awk理解)。awk --version`awk -W version`

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

词汇表:

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

+ POSIX**规定的默认值**是**换行符**,如下所示`

`;也就是说,输入**默认被分成几行

+ `awk`在的命令行上,`RS`可以指定为`-v RS=<sep>`。
+ POSIX 限制`RS`为*文字、单字符*值,但 GNU Awk 和 Mawk 支持可以*扩展正则表达式的**多字符*值(BWK Awk 不*支持*)。
  • FS输入字段分隔符,描述如何将每个记录拆分成字段;它可以是扩展的正则表达式

+ 在`awk`的命令行上,`FS`可以指定为`-F <sep>`(或`-v FS=<sep>`)。
+ **POSIX规定的默认值*正式*是一个*空格*(`0x20`),但该空格并非*按字面*意思解释为(唯一)分隔符,而是具有*特殊含义***;见下文。

默认情况下

  • 任何空格 和/或 制表和/或换行符都被视为字段分隔符

  • 忽略前导和尾随运行

POSIX 规范使用空格和制表符的抽象<blank>,这适用于所有语言环境,但可能包含特定语言环境的附加字符 - 我不知道是否存在这样的语言环境。

请注意,使用默认的输入记录分隔符RS),`
换行符**通常*不会*作为字段分隔符进入图片**,因为在这种情况下**没有记录*本身* 包含
`**。

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

  • *RS设置为一个值时,会导致记录本身*包含`
    实例**(例如,当RS`设置为空字符串时;见下文)。

  • 一般来说,当该split()函数用于将字符串拆分为数组元素时,不需要显式字段分隔符参数。

    • 即使在默认值生效的情况下输入记录不包含实例,但是当在来自不同源(例如,通过选项传递的变量或伪文件名)的多行字符串上调用该函数时,如果没有明确的字段分隔符参数,则始终将其视为字段分隔符。`
      RSsplit()-v

`


重要的非违约考虑因素

  • 字符串分配给RS具有特殊含义:它以段落模式读取输入,这意味着输入被按非空行分解为记录并且忽略前导和尾随的空行

  • 当您为分配除文字空间之外任何内容FS时,的解释FS 会发生根本性的变化

+ **单个字符或指定字符*集中***的每个字符被***单独*****识别为字段分隔符**- 而不是像默认的那样连续
*运行****。***
    - 例如,设置`FS`为`[ ]`- 即使它*实际上*相当于一个空格 - 也会导致每个记录中的每个*单独的*空格实例被视为字段分隔符。
    - 为了识别*连续的字符*`+`,必须使用正则表达式量词(重复符号) ;例如,将*连续*`[    ]+`的制表符识别为单个分隔符。
+ ***前导和尾随*分隔符不会被忽略**,而是用来分隔*空*字段。
+ **设置`FS`为*空字符串***意味着记录的**每个*字符*****都是其自己的字段**。
  • 根据POSIX 的规定,如果*RS设置为空字符串(段落模式),则换行符*(`
    )*也*将被视为字段分隔符**,而不管 的值如何FS`。


[1] 不幸的是,当您使用选项( ) 强制遵循 POSIX 合规性时, GNU Awk 至少在版本 4.1.3 之前遵守有关字段分隔符的过时POSIX 标准:当该选项生效并设置为非值时,换行符 (实例) 不会被识别为字段分隔符。GNU Awk 手册详细说明了过时的行为(但忽略了提到当设置为字符串时它不适用)。POSIX 标准在 2008 年进行了更改(参见注释),当 具有其默认值时,也会考虑换行符字段分隔符- 正如 GNU Awk 一直在没有(的情况下所做的那样)。
以下是 2 个验证上述行为的命令:-P`--posixRS
RSFS -P`--posix

  • -P在有效并RS设置为空字符串的情况下,仍然`
    `被视为字段分隔符:

`gawk -P -F' ' -v RS='' '{ printf "<%s>, <%s>
", $1, $2 }' <<< $'a
b'`

  • 实际上-P,如果非空 RS,`
    `则不将其视为字段分隔符 - 这是过时的行为:根据 GNU Awk 维护者的说法,

`gawk -P -F' ' -v RS='|' '{ printf "<%s>, <%s>
", $1, $2 }' <<< $'a
b'`

修复即将到来;预计在版本4.2中(未给出时间框架)。

(向 @JohnKugelman 和 @EdMorton 表示感谢,感谢他们的帮助。)

解决方案 2:

这个问题the default delimiter is only space for awk?比较模糊,但我会尽力回答您可能提出的两个问题。

该变量的默认值FS(保存字段分隔符,告诉 awk 在读取记录时如何将记录分隔成字段)是一个空格字符。

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

  1. 在字段拆分期间,前导和尾随空格将被忽略。

  2. 字段由连续的空格字符链分隔,包括空格、制表符和换行符。

  3. 如果您想使用文字空白字符作为字段分隔符,则必须将其指定为,[ ]而不是像在正则表达式中那样仅指定独立的文字空白字符。

除了在读取输入时使用字段分隔符将记录拆分为字段之外,它们还用于其他一些上下文中,例如,的第 3 个参数split(),因此,了解哪些上下文需要字符串、正则表达式或 fieldsep 并且手册页清楚地指定每一个非常重要。

除其他事项外,以上内容解释了这一点:

$ echo ' a b c ' | awk '{printf "%d: <%s> <%s> <%s>
", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F' ' '{printf "%d: <%s> <%s> <%s>
", NF, $1, $2, $3}'
3: <a> <b> <c>
$ echo ' a b c ' | awk -F'[ ]' '{printf "%d: <%s> <%s> <%s>
", NF, $1, $2, $3}'                              
5: <> <a> <b>

因此,如果您不明白为什么前两个产生相同的输出而最后一个产生不同的输出,请询问。

解决方案 3:

让我们看一下 GNU awk 手册页:

FS— 输入字段分隔符,默认为空格。请参阅上文的字段

转至Fields部分!

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

解决方案 4:

'[ ]+' 对我来说很管用。运行awk -W version以获取 awk 版本。我的是GNU Awk 4.0.2

# cat a.txt
tcp        0      0 10.192.25.199:65002     0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:26895         0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:18422           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 10.192.25.199:8888      0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:50010           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:50075           0.0.0.0:*               LISTEN
tcp        0      0 10.192.25.199:8093      0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:8670            0.0.0.0:*               LISTEN

例如,我想获取 Listen 端口。因此我需要使用 awk 默认分隔符加上 ':'

# cat a.txt  | awk -F '[ ]+|:' '{print $5}'
65002
26895
111
18422
22
8888
50010
50075
8093
8670

如果你只想测试默认分隔符,你可以运行

# cat a.txt  | awk -F '[ ]+' '{print $4}'
10.192.25.199:65002
127.0.0.1:26895
0.0.0.0:111
0.0.0.0:18422
0.0.0.0:22
10.192.25.199:8888
0.0.0.0:50010
0.0.0.0:50075
10.192.25.199:8093
0.0.0.0:8670

结果正如预期。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用