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 / 问题 / 748147
Accepted
Hölderlin
Hölderlin
Asked: 2023-06-07 03:32:41 +0800 CST2023-06-07 03:32:41 +0800 CST 2023-06-07 03:32:41 +0800 CST

使用模式空间和保持空间的 sed 性能

  • 772

给定一个 425M 大小的文本文件,内容如下:

--START--
Data=asdfasdf
Device=B
Lorem=Ipsum
--END--
--START--
Data=asdfasdf
Lorem=Ipsum
Device=A
--END--
--START--
Device=B
Data=asdfasdf
--END--
...

任务sed是打印--START--和之间的所有内容--END--,其中Device=A包含 。这里和这里提供了两种解决方案。两个命令之间存在巨大的执行时间差异。第二个命令相当快,但需要更多的说明来说明它是如何工作的吗?

$ sed -n '/--START--/{:a;N;/--END--/!ba; /Device=A/p}' file
$ sed 'H;/--START--/h;/--END--/!d;x;/Device=A/!d' file

第一条命令的说明:

怎么运行的:

/--START--/{...}每次我们到达包含 的行时--START--,运行大括号内的命令{...}。

:a;定义标签“a”。

N;阅读下一行并将其添加到模式空间。

/--END--/!ba除非模式空间现在包含--END--,否则跳回标签a。

/Device=A/p如果我们到达此处,则意味着模式空间以 开始--START--并以 结束--END--。此外,如果模式空间包含Device=A,则打印 ( p) 它。

2号命令说明:

sed 'H              #add line to hold space
     /--START--/h   #put START into hold space (substitute holded in)
     /--END--/!d    #clean pattern space (start next line) if not END
     x              #put hold space into pattern space
     /Device=A/!d   #clean pattern space if it have not "Device=A"
    ' file
sed
  • 1 1 个回答
  • 82 Views

1 个回答

  • Voted
  1. Best Answer
    don_crissti
    2023-06-09T04:56:36+08:002023-06-09T04:56:36+08:00

    要记住的一件事是正则表达式匹配是“昂贵的”......所以模式缓冲区中的东西越多,搜索速度就越慢。
    在这种特殊情况下,sed必须找到三种模式(让我们将它们编号为 1、2 和 3):范围 START (1)、范围 END (2) 和该范围内的 MATCH (3)(如果有)。

    两种解决方案之间的主要区别在于用于存储范围内所有行的缓冲区,这又决定了如何检测范围的结束。

    第一个解决方案通过在每一行上搜索 START (1) 来工作,一旦找到它,它就会开始将行附加到模式空间,并且必须在每次迭代时检查范围的 END (2)(iow 每次它添加一个模式空间中数据的新行,它再次在整个缓冲区中搜索 END 以便知道何时停止)。一旦找到它,它就会在整个模式空间中搜索 MATCH (3)。

    第二个解决方案的工作方式不同:它通过 无条件地在保留空间中累积行H,它对每一行进行两次模式匹配:分别确定范围的开始(1)和结束(2)。这是非常快的。一旦它检测到范围的结束,它就会x更改缓冲区(因此现在模式空间包含在保持空间中累积的所有行)并在整个模式空间中搜索 MATCH (3)。

    如您所见,(3)在这两种情况下是相同的:一旦模式空间包含从 START 到 END 的所有行sed,两个脚本都会运行一次 MATCH 搜索。因此,将两个解决方案分开的不是对 MATCH 的搜索。这里的主要区别是由 (2) 引起的: 第二种解决方案在每一行上搜索 END - 如果该行不包含 END,它将从模式空间中删除它并重新启动循环,即它拉入另一行,然后再次, 试图找到 END 等等。在找到 END 之前,模式空间中永远不会超过一行。 相比之下,第一个解决方案将执行
    d
    a;N;/--END--/!ba 在越来越大的文本缓冲区上一遍又一遍,即使与上一次运行的差异只包含一行。在处理大型文本文件时,这绝不是一件好事——想象一下 START-END 范围跨越数千行......

    简而言之:搜索范围的 END 会减慢它的速度。


    与第二种技术相比,第一种技术有多慢的一个很好的例子可以在这里找到:

    将列表变成带分隔符的单行

    正如您在我的测试中看到的那样,第一个解决方案甚至无法完成测试。

    • 3

相关问题

  • 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