AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 493141
Accepted
Just a learner
Just a learner
Asked: 2019-01-08 20:00:35 +0800 CST2019-01-08 20:00:35 +0800 CST 2019-01-08 20:00:35 +0800 CST

Gnu sed,打印时p命令会附加换行符吗?

  • 772
root@u1804:~# sed --version
sed (GNU sed) 4.5
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jay Fenlason, Tom Lord, Ken Pizzini,
and Paolo Bonzini.
GNU sed home page: <https://www.gnu.org/software/sed/>.
General help using GNU software: <https://www.gnu.org/gethelp/>.
E-mail bug reports to: <[email protected]>.
root@u1804:~#

我是 sed 的新手,我根据我的理解在 sed 的工作流程下创建了(如果您发现任何错误,请纠正我)。

在此处输入图像描述

因此,模式空间的默认自动打印似乎总是在末尾包含一个换行符。我的问题是,是否也会p包含换行符?我有以下例子。

root@u1804:~# seq 3 | sed -rn 'p'
1
2
3
root@u1804:

这里每个数字末尾的换行符是由 sed 自己添加的(参见图表“将换行符添加回模式空间”)。所以它似乎p不会附加换行符。但是,请参见下面的示例。

root@u1804:~# seq 3 | sed -rn 'x;p;x;p'

1

2

3
root@u1804:~#

这里x用保持空间交换模式空间,这将导致一个空的模式空间。现在p应用于模式空间(其中没有任何内容)应该什么都不打印。但根据结果,这里似乎p打印了一个换行符。对我来说,这似乎是不一致的行为。谁能解释一下?

sed
  • 3 3 个回答
  • 1886 Views

3 个回答

  • Voted
  1. Best Answer
    fra-san
    2019-01-10T06:53:03+08:002019-01-10T06:53:03+08:00

    要回答您的主要问题:

    GNU将在执行命令时sed附加一个字符,除非输入行缺少其终止字符(请参阅下面关于行的说明)。<newline>p<newline>

    据我所知,sed'p标志及其自动打印功能实现了相同的逻辑来输出模式空间:如果尾随<newline>字符被删除,则将其添加回来;否则他们不会。

    例子:

    $ printf '%s\n%s' '4' '5' | sed ';' | hexdump -C      # auto-print
    00000000  34 0a 35                                          |4.5|
    00000003
    
    $ printf '%s\n%s' '4' '5' | sed -n 'p;' | hexdump -C  # no auto-print; p flag
    00000000  34 0a 35                                          |4.5|
    00000003
    

    在这两种情况下,对于没有字符的输入行,输出中都没有<newline>字符 ( 0a)。


    关于您的图表:

    “将换行符添加到模式空间”可能不准确,因为该<newline>字符未放入模式空间1。此外,该步骤与-n选项无关 - 但这不会使图表出错;相反,它可能应该合并到“打印模式空间”中。
    不过,我同意你关于文档不够清晰的观点。

    1您在自己的答案中引用的句子“模式空间的内容被打印到输出流中,如果删除了尾随换行符,则添加回”,这意味着附加到流中,而不是模式空间中。当然,由于花样空间很快就被清除了,这是一个非常次要的点<newline>


    关于涉及x标志的测试:

    在内部,模式空间和保持空间是结构,“我的尾随<newline>字符被丢弃了吗?” 是他们的一员。我们称它为chompedsed (顺便说一下,它在 的源代码中命名)。
    模式空间由读取行填充,其chomped属性取决于该行的终止方式:true如果它以<newline>字符结尾,false否则。另一方面,保持空间被初始化为空,并且它的chomped属性被设置为true。
    因此,当您交换模式空间和保持空间并打印最初的保持和现在的模式时,<newline>会打印一个字符。

    示例 - 这些命令具有相同的输出:

    $ printf '\n' | sed -n 'p;' | hexdump -C        # input is only a <newline>
    00000000  0a                                                |.|
    00000001
    
    $ printf '%s' '5' | sed -n 'x;p;' | hexdump -C  # input has no <newline>
    00000000  0a                                                |.|
    00000001
    

    (我只是简单地看了一下sed's 的代码,所以这很可能不准确)。


    关于行(澄清从对您的答案的评论开始):

    不用说,没有终止字符的行<newline>是一个有问题的概念。引用POSIX:

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

    此外,POSIX定义了一个文本文件:

    3.403 文本文件
    包含组织成零行或多行的字符的文件。...

    最后,POSIX on sed(bold mine):

    描述
    该sed实用程序是一个流编辑器,应读取一个或多个文本文件,根据编辑命令脚本进行编辑更改,并将结果写入标准输出。...

    不过, GNUsed在定义其输入时似乎不那么严格:

    sed是一个流编辑器。流编辑器用于对输入流(文件或来自管道的输入)执行基本的文本转换。...

    所以,关于我的第一句话,我们应该考虑到,对于 GNU sed,读入模式空间的内容不一定是格式良好的文本行。

    • 5
  2. Just a learner
    2019-01-09T08:34:47+08:002019-01-09T08:34:47+08:00

    我编辑了我的答案,只包含一个基于 fra-san 答案的更新图表。唯一目的是供新的 sed 用户参考。

    在此处输入图像描述

    • 4
  3. user232326
    2019-01-12T01:57:15+08:002019-01-12T01:57:15+08:00

    在 GNU sed 中:该命令p仅在源文本中添加一个尾随换行符(当放置在模式空间中时从输入中删除一个),但如果将其他文本打印到同一流中,也会添加一个前导换行符。

    仅在最后一行的输入中可能缺少尾随换行符。

     $ printf 'abc' | od -An -c
        a   b   c                                 # no newline.
    
     $ printf 'abc' | sed '' | od -An -c
        a   b   c                                 # also no newline.
    
     $ printf 'abc' | sed -n 'p' | od -An -c
        a   b   c                                 # still no newline.
    
     $ printf 'abc' | sed -n 'p;p' | od -An -c
        a   b   c  \n   a   b   c                 # leading newline added.
    

    仅打印最后一行,仅当源文件在最后一行已经有换行时才会有新行:

     $ printf 'abc\ndef' | sed -n '$p' | od -An -c
        d   e   f
    

    来自信息 sed:

    ---------- 脚注 ----------

    (1) 实际上,如果 'sed' 打印一行没有终止换行符,它仍然会在将更多文本发送到同一输出流时打印缺少的换行符,这会给出“最不期望的惊喜”,即使它没有使诸如“sed -n p”之类的命令与“cat”完全相同。

    其他一些 sed 版本可能会添加尾随换行符和/或发出警告。

    • 1

相关问题

  • Linux grep文件1中的内容在文件2中[重复]

  • 如何在第三个逗号后用条件grep行

  • 根据第一个逗号之前的匹配删除重复行数

  • 如何改进这个字符转换脚本?

  • 如何删除两行之间的单行

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve