bash& sed:用for循环替换变量中的多个字符串

时间:2014-01-25 12:44:55

标签: string bash replace sed awk

使用bash,我试图用sed替换存储变量中的多行,然后使用行更改打印变量。

list变量看起来像这样 - virtmx元素都是唯一的 - 不重复

$ list variable:

domain1.com     =====>  dest.domain.com:25
domain2.com     =====>  virtmx-0050:25
domain3.com     =====>  dest.domain2.com:25
domain4.com     =====>  domain.example.com:25
domain5.com     =====>  dest.domain3.com:25
domain6.com     =====>  virtmx-0051:25
domain7.com     =====>  dest.domain4.com:25
domain8.com     =====>  dest.domain5.com:25
domain9.com     =====>  dest.domain6.com:25

我希望将所有virtmx- [num]替换为系统中文件中的另一行。

somefile.log同时包含行[num]和替换行:

file.log中的行示例:

cat /somedir/somefile.log | grep virtmx-*
<mta id="50" host="virtmx-0050:25" dns_type="MX" desc="mxgroupname">
<mta id="51" host="virtmx-0051:25" dns_type="MX" desc="mxgroupname2">

使用awk进行线提取的示例:

cat /somedir/file.log | grep virtmx-0050 | awk -F "\"" '{print $4,$8}'
virtmx-0050:25 mxgroupname
virtmx-0051:25 mxgroupname2

期望的输出:

domain1.com     =====>  dest.domain.com:25
domain2.com     =====>  mxgroupname
domain3.com     =====>  dest.domain2.com:25
domain4.com     =====>  domain.example.com:25
domain5.com     =====>  dest.domain3.com:25
domain6.com     =====>  mxgroupname2
domain7.com     =====>  dest.domain4.com:25
domain8.com     =====>  dest.domain5.com:25
domain9.com     =====>  dest.domain6.com:25

$ listoflines只包含这些行:

line1
line2

我正在使用awk提取行然后创建一个sed替换字符串 - 我用它来替换$ output变量中的条目:

line1/replacement1

我认为我很接近但是下面的代码只是替换循环中的第一个实例然后重新开始并使用新的替换再次打印整个变量,但是缺少第一个。相反,我想用所有替换打印整个变量一次。替换的数量可能会有所不同,这就是我尝试使用for循环的原因。

for i in $listoflines
do
    replace=`cat /dir/somemfile.log | grep $i | awk -F "\"" '{print $4,$8}' | sed 's/ /\//'`
    echo "$list" | sed 's/'$replace'/'
done

2 个答案:

答案 0 :(得分:2)

我远离awk大师,但基于glenn's回答简单的尝试

awk '
    NR==FNR {split($0,x,"\""); r[x[4]]=x[8]; next}
    /virtmx/ {$3=r[$3]}
    {print $1,$2,$3}
' file.log <(echo "$list")

输出:

domain1.com =====> dest.domain.com:25
domain2.com =====> mxgroupname
domain3.com =====> dest.domain2.com:25
domain4.com =====> domain.example.com:25
domain5.com =====> dest.domain3.com:25
domain6.com =====> mxgroupname2
domain7.com =====> dest.domain4.com:25
domain8.com =====> dest.domain5.com:25
domain9.com =====> dest.domain6.com:25

讨论:

  • 将两个“文件”发送给awk,file.log<(echo "$list")
  • NR==FNR用于仅处理第一个文件

    1. file.log上拆分"并指定一个带有pattern-&gt;替换的关联数组r
    2. $list作为文件进行处理,如果行匹配virtmx则使用assoc数组替换,最后打印三列。

修改:在第一行中使用NR!=FNR删除next

答案 1 :(得分:0)

你应该做什么:

  • 在awk中,而不是创建一个sed字符串“line1 / replacement”,创建一个关联数组repl[line1] = replacement
  • 然后,仍然在awk中,处理$ output(使用进程替换来使用类似文件的东西),然后使用if ($NF in repl) $NF = repl[$NF]; print

我需要查看您现有的代码,以便为您提供更具体的建议。