Awk 为什么不替换最后一个新行字符

Awk 为什么不替换最后一个新行字符,awk,Awk,要由awk处理的文件 hello world hello Jack hello Jim Hello Marry Hello Bob Hello Everyone 我的命令是awk'BEGIN{RS=“;FS=“\n”;}{gsub(“\n”,“@”);print}。awk手册说,当RS设置为null(空?)字符串时,记录用空行分隔。因此,预期结果是 hello world@hello Jack@hello Jim@ hello Marry@hello Bob@hello Everyone@

要由awk处理的文件

hello world
hello Jack
hello Jim

Hello Marry
Hello Bob
Hello Everyone
我的命令是
awk'BEGIN{RS=“;FS=“\n”;}{gsub(“\n”,“@”);print}
。awk手册说,当RS设置为null(空?)字符串时,记录用空行分隔。因此,预期结果是

hello world@hello Jack@hello Jim@
hello Marry@hello Bob@hello Everyone@
但实际上,结果是

hello world@hello Jack@hello Jim
hello Marry@hello Bob@hello Everyone

最后一个新行字符不替换为
@
。是因为当awk读取内容并将内容剪切到字段时,记录的最后一个新行字符由awk指定吗?是否有一些关于awk如何读取和剪切以及如何使用模式和操作处理字段的详细手册?谢谢。

您可以查看此页面:

它说: 当RS设置为空字符串,FS设置为单个字符时,换行符始终充当字段分隔符

因此,您不必指定
FS=\n
,如果您说
RS=”“
,它会自动发生

为了产生预期输出,您可以执行以下操作:

BEGIN{
    RS=""
} 
{
    $0=$0 ORS
    gsub("\n","@")
    print
}

输出中没有尾随
@
的原因是:

  • 如果设置了
    RS=“”
    ,则与
    RS=“\n\n+”
    类似(*但有所不同,我稍后解释)。因此,awk将使用最长(>=2)的连续换行符作为
    RS

  • 查看您的数据,在
    Jim
    之后有两个
    \n
    s,直到下一个文本块。因此,awk将把这两个
    \n
    作为RS,因此在您的记录(Jim记录)中有no结尾
    \n
    。当然,您的
    gsub
    不会取代它。您可以看到输出中的换行符,它是由
    print

  • 输出中的第二行也没有结尾
    @
    ,因为我们使用了
    RS=“
    而不是
    RS=“\n\n+”
    。重要的区别是,对于
    RS=”“
    ,将忽略输入数据文件中的前导换行符,如果文件在最后一条记录之后结束时没有额外的空行,则将从记录中删除最后一条换行符。这就是为什么在输出行2中没有尾随的
    @

如果将其更改为
RS=“\n\n+”
,则应在输出的第2行中看到结尾
@


我猜你想知道为什么你得到的结果不是你所期望的。但不要试图达到你的预期产出,对吗?如果您的问题是如何获得该输出,我将编辑我的答案。

如果操作仅在
$0
上完成,使用或不使用
FS
没有任何区别。这不是重点。使用
FS='\n'
,将忽略空格,因为
FS
,这是有用的,取决于需求。@Kent感谢您的评论,但我不确定我是否理解您的观点:)@HåkonHægland该链接有用。但是在我读过之后,我怀疑我是否涉及到一个问题,这个问题的答案取决于版本、POSIX和GNU扩展。是的,我只是想找出原因。我尝试了
RS=“\n\n+”
。但结果取决于awk的版本。在
3.1.3
中,末尾没有
@
。但是在
3.1.7
中,
@
是存在的。@Donglei我用
GNU Awk 4.1.0
进行了测试,最后用
\n\n+
有一个
@
。(使用您的示例输入)