繁体   English   中英

循环中的Unix'sed'命令

[英]Unix 'sed' command in a loop

我想用sed命令编写脚本,因为我猜这是最适合我的目标的命令。 有一个名为NAME的文件,该文件由不同的名称组成,这些名称在以下列中排序:

STEVE
JOHN
CLARE

该脚本应执行以下操作:

  1. NAME文件中获取$value
  2. sed 's/"'$i'"/ARNOLD/g' test1.log>test2.log替换$value为常量值('ARNOLD')(test1和test2文件相同)。

我准备了脚本的版本,但它仅适用于名称列表中的最新值:

while read i; do sed 's/'"$i"'/ARNOLD/g' test1.log >test2.log ; done<name

您可能需要这样的东西:

awk 'NR==FNR{names[$0];next} {for (name in names) gsub(name,"ARNOLD")}' NAME test1.log >test2.log

但是没有示例输入和预期输出,这是一个猜测,并且它具有非锚定的潜在问题,因为到目前为止发布的所有sed脚本都存在这样的问题,例如,将“ JOHNSON”更改为“ ARNOLDSON”。 通过GNU awk,您可以使用单词边界解决该问题:

awk 'NR==FNR{names[$0];next} {for (name in names) gsub("\\<"name"\\>","ARNOLD")}' NAME test1.log >test2.log

但是可能会有其他问题,直到我们看到您的样本输入和预期输出,我们才能为您提供帮助。

使用awk vs shell + sed的wrt(从注释中删除):

每次编写shell循环只是为了操纵文本时,您都会使用错误的方法。 有关此主题的讨论,请参见https://unix.stackexchange.com/q/169716 但是,从本质上讲-UNIX Shell是一种环境,可以使用一种语言来对UNIX工具进行调用,以对这些调用进行排序。 Awk是由发明Shell的人创建的工具,用于为UNIX进行文本处理。 因此,只需使用它。 在shell中,您可以编写看起来像它们一样可以完成工作的脚本,但是实际上要使shell语法正确地进行文本操作非常困难,因为这不是设计的目的(例如, while read i不是怎么阅读)在shell中输入-至少需要while IFS= read -ri时输入),即使您设法正确使用语法,与awk相比,它的运行速度也非常慢。

如果您打算在UNIX中进行任何文本操作,您应该读一读Arnold Robbins的《有效Awk编程》,第4版,否则您将浪费大量时间来创建复杂,低效,错误,难以维护的内容,否则通常糟糕的Shell脚本。

您可以使用sed生成更改,然后将第一个的输出用作脚本,以供另一个sed读取

sed 's/.*/s\/&\/ARNOLD\/g/' NAME | sed -f- test1.log >test2.log

说明

sed 's/.*/s\/&\/ARNOLD\/g/'

创造

s/STEVE/ARNOLD/g
s/JOHN/ARNOLD/g
s/CLARE/ARNOLD/g

然后通过管道传输到

sed -f-

-f读取脚本文件
-是管道的标准配置

每次脚本循环时,它都以未修改的test1.log并更改一个名称。 这意味着只有姓氏更改才会出现在test2.log

每个循环都撤消所有先前的更改。

从原始test1.log复制后,可以覆盖test1.log。 您可以使用sed -i

sed 's/'"$i"'/ARNOLD/g' test1.log >test2.log && mv test2.log test1.log

此解决方案需要大量I / O,并且比@Ed的解决方案差。 我只是添加了它以显示如何解决@msw注意到的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM