【问题标题】:multiple sed commands: when semicolon, when pipeline?多个 sed 命令:何时分号,何时管道?
【发布时间】:2016-08-08 16:01:08
【问题描述】:

当我在sed中构造一个复杂的操作时,我经常从

cat infile | sed 'expression1' | sed 'expr2' ...

然后优化成

cat infile | sed 'expr1;expr2;expr3' | sed 'expr4' | sed 'expr5;expr6' ...

有哪些准则可以将表达式与分号组合成一个命令? 到目前为止,我只是临时组合s///'s,而不是组合//d's。

(优化是为了运行几千万次。没错,就是measurably faster。)

(在此处而不是在 superuser.com 上发布,因为关于 sed 的问题要少 20 倍。)

【问题讨论】:

  • wrt When I construct a complicated operation in sed - 不要那样做! sed 用于在单个行上进行简单替换,仅此而已。对于其他任何事情,您都应该使用 awk。结果将比一组复杂的 sed 操作更清晰、更快、更便携、更健壮、更易于维护并且在其他方​​面都更好。

标签: bash sed pipe


【解决方案1】:

您正在执行的操作在每种情况下都完全不同。

当您使用管道“组合” sed 命令时,每次调用 sed 都会处理整个文件。这会产生为管道的每个部分启动单独流程的成本。

当您使用以分号分隔的命令列表时,每个命令将依次应用于文件中的每一行,使用单个 sed 实例。

根据您使用的命令,这两件事的输出可能会有很大不同!

如果您不喜欢使用分号来分隔命令,我会建议另一种选择:使用sed -e 'expr1' -e 'expr2' -e 'expr3' file。或者,包括 sed 在内的许多工具都支持 -f 来传递包含命令的文件。为了清楚起见,您可以将每个命令放在换行符上,而不是使用分号。

【讨论】:

  • 使用管道意味着管道接收端的命令延迟启动(或延迟开始处理数据)直到发送端的命令完成/关闭其管端。使用分号分隔的单独的sed 命令会发生类似的情况,但不会使用管道。
  • @John 好点,我从答案中删除了那部分。我开始怀疑输出不同的部分,现在我想起来了!
【解决方案2】:

一般sd可以和平共处。当不同的命令相互交互时,您可能不得不分解并使用单独的脚本,或者切换到具有变量等的更丰富的语言。

例如,一个sed 脚本将数千个分隔符添加到缺少它们的数字上,可能应该与其他处理完全分开。从长远来看,模块化可能比任何可能的效率提升更重要。

【讨论】:

    【解决方案3】:

    有哪些准则可以将表达式与分号组合成一个命令?到目前为止,我只是临时组合 s///'s,而不是组合 //d's。

    sed 的命令远不止sd。但是,如果这些是您唯一使用的,那么您可以在同一 sed 运行中加入任意数量的用户。结果将与多个单命令seds 的管道相同。但是,如果您要这样做,请考虑使用命令文件,如@anubhava 建议的那样,或者通过自己的-e 参数给出每个独立的表达式;任何一个都比由多个分号分隔的命令组成的单个表达式要清晰得多。

    即使您使用其他命令,在大多数情况下,通过单个 sed 进程执行一系列命令会得到与通过单独的 sed 以相同顺序执行相同命令相同的结果过程。我能想到的主要例外涉及必须相互依赖的命令,例如标签和分支;操纵保持空间及其周围的命令;分组在大括号内的命令 ({});以及sed -n 下的p 命令。

    话虽如此,sed 程序很快就会变得非常神秘。如果您正在编写一个复杂的转换,那么请考虑仔细采纳@EdMorton 的建议并将整个内容编写为(单个)awk 程序,而不是一个或多个sed 程序。

    【讨论】:

      【解决方案4】:

      最好避免使用多个sed

      sed -f mycmd.awk
      

      mycmd.awk 将包含在单独的行中列出的每个 sed 命令。

      根据man sed

      -f command_file
      将文件 command_file 中的编辑命令附加到命令列表中。编辑命令应分别列在单独的行上。

      【讨论】:

      • 虽然您绝对可以调用您的 sed 脚本 mycmd.awk,但我认为这对任何必须理解它的人来说都是残酷的 ;)
      • @BenjaminW。不过,这确实表明他的想法是朝着正确的方向倾斜 ;-)。
      猜你喜欢
      • 2014-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-04
      • 1970-01-01
      • 2022-06-21
      • 1970-01-01
      相关资源
      最近更新 更多