[英]Unix 'sed' command in a loop
我想用sed
命令编写脚本,因为我猜这是最适合我的目标的命令。 有一个名为NAME
的文件,该文件由不同的名称组成,这些名称在以下列中排序:
STEVE
JOHN
CLARE
该脚本应执行以下操作:
NAME
文件中获取$value
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.