【问题标题】:In awk, why are "" and "\n\n" treated the same for the RS parameter?在 awk 中,为什么 "" 和 "\n\n" 对于 RS 参数的处理方式相同?
【发布时间】:2019-09-09 09:46:32
【问题描述】:

这是文件的内容:

Person Name
123 High Street
(222) 466-1234

Another person
487 High Street
(523) 643-8754

这两件事给出了相同的结果:

$ awk 'BEGIN{FS="\n"; RS="\n\n"} {print $1, $3}' file_contents
$ awk 'BEGIN{FS="\n"; RS=""} {print $1, $3}' file_contents

两种情况给出的结果都是:

Person Name (222) 466-1234
Another person (523) 643-8754

RS="\n\n"其实是有道理的,但是为什么RS=""也被这样对待呢?

【问题讨论】:

    标签: linux unix awk


    【解决方案1】:

    他们的待遇不同。

    • RS=""all awks 中调用段落模式,因此输入被分成由连续的空行序列分隔的记录,如果现有 FS 是单个字符,则将换行符添加到 FS(注意: POSIX 标准在这方面是不正确的,因为它暗示 \n 将被添加到任何 FS 中,但事实并非如此,请参阅 https://lists.gnu.org/archive/html/bug-gawk/2019-04/msg00029.html)。
    • RS="\n\n"GNU awk 中工作以将记录分隔符设置为单个空行并且不影响 FS。在所有其他 awk 中,第二个 \n 将被忽略(RS 中超过 1 个字符是每个 POSIX 未定义的行为,因此它们可以做任何事情,但这是迄今为止最常见的实现)。

    看看当您的 2 个文本块之间有 3 个空行并使用 \n 以外的 FS(例如 ,)时会发生什么:

    $ cat file
    Person Name
    123 High Street
    (222) 466-1234
    
    
    
    Another person
    487 High Street
    (523) 643-8754
    

    .

    $ gawk 'BEGIN{FS=","; RS=""} {print NR, NF, "<" $0 ">\n"}' file
    1 3 <Person Name
    123 High Street
    (222) 466-1234>
    
    2 3 <Another person
    487 High Street
    (523) 643-8754>
    

    .

    $ gawk --posix 'BEGIN{FS=","; RS=""} {print NR, NF, "<" $0 ">\n"}' file
    1 3 <Person Name
    123 High Street
    (222) 466-1234>
    
    2 3 <Another person
    487 High Street
    (523) 643-8754>
    

    .

    $ gawk 'BEGIN{FS=","; RS="\n\n"} {print NR, NF, "<" $0 ">\n"}' file
    1 1 <Person Name
    123 High Street
    (222) 466-1234>
    
    2 0 <>
    
    3 1 <Another person
    487 High Street
    (523) 643-8754>
    

    .

    $ gawk --posix 'BEGIN{FS=","; RS="\n\n"} {print NR, NF, "<" $0 ">\n"}' file
    1 1 <Person Name>
    
    2 1 <123 High Street>
    
    3 1 <(222) 466-1234>
    
    4 0 <>
    
    5 0 <>
    
    6 0 <>
    
    7 1 <Another person>
    
    8 1 <487 High Street>
    
    9 1 <(523) 643-8754>
    
    10 0 <>
    

    注意NRNF 的不同值以及正在打印的不同$0 内容。

    【讨论】:

    • 如果我们设置FS=","(如第一个示例),我希望文件的所有内容都是一条记录,因为没有",\n" 的实例(你说这是 POSIX 对单个 char FS 所做的,添加了一个 \n) 并且它将在 EOF 处结束记录。为什么有两条记录?
    • 提供--posix 选项有何不同?从我在这里读到的内容:gnu.org/software/gawk/manual/html_node/Options.html 它只是禁用了一堆与 POSIX 兼容的 gawk 功能。 gawk --posix = awk?为什么要专门用这个选项再举两个例子?此外,这可能是相关的,但您能否澄清“GNU awk”和“所有 awk”之间的区别是什么?搜索不会产生任何有用的东西。
    • @herophant "将 \n 添加到 FS" 并不意味着将 , 更改为 ,\n,而是将 , 更改为 [,\n], i.e. **either** ,` 或 \n 不分隔字段, 后跟 \n。添加--posix 会禁用包括多字符RS 在内的gawk 功能,因此RS="\n\n" 则意味着RS="\n"。 gawk、mawk、tawk、BSD awk、nawk、/usr/xpg4/bin/awk 和busybox awk(我相信其他人)都是awk,就像747 和空中客车和里尔喷气机都是飞机一样。所以 gawk 是 awk 并且 gawk --posix 也是 awk。
    • POSIX 是大多数 awks 至少遵守的标准,例如gawk,提供额外的扩展,就像飞机有一些最低标准(例如,起飞和降落的能力!)但各种飞机在此之上可能有不同的特性(例如道具与喷气机)。为什么我要添加更多示例?因此,您可以看到启用默认扩展的 gawk 的行为与 POSIX 兼容的 awk(包括禁用扩展的 gawk)在RS="" 和 `RS="\n\n" 的情况下的行为。
    • 是的,你是对的,awk 和 gawk 在我的系统上是一样的。谢谢你的详细解释。
    【解决方案2】:

    因为POSIX awk specification是这么说的。

    如果RS 为空,则记录由&lt;newline&gt; 加上一个或多个空行组成的序列分隔,前导或尾随空行不应导致输入的开头或结尾处为空记录,并且无论FS 的值是什么,&lt;newline&gt; 始终是字段分隔符。

    【讨论】:

    • 仅供参考,POSIX 标准说 no matter what the value of FS is 是错误的 - 仅当 FS 是单个字符时才添加换行符。他们已收到通知,如果您关心,请参阅 lists.gnu.org/archive/html/bug-gawk/2019-04/msg00029.html 了解背景信息。
    • @Ed 感谢您提供的信息。不过,我会保留我的答案,因为 POSIX 标准还没有修复它。
    猜你喜欢
    • 1970-01-01
    • 2021-10-01
    • 2020-10-19
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    相关资源
    最近更新 更多