匹配模式后修改第n行

时间:2014-01-08 18:47:56

标签: regex shell sed awk

我需要修改包含大量ldif的文件。基本上文件的结构是这样的。我将此文件称为文件-1。

 cn: username1
 gidNumber: 222
 loginShell: /bin/bash
 objectClass: inetOrgPerson
 objectClass: shadowAccount
 uid: username1
 mail:

 cn: username2
 ...

所以我需要匹配cn:example1然后更改相应的邮件:即匹配后的第6行。我有另一个名为file-2的文件,我将从中获取新值来修改。文件-2具有这样的语法。

 username1 abc@email.com
 username2 bcd@email.com
 ...

所以我想这样做。如果找到匹配项,则将文件-2中的username1与文件-1中的用户匹配,然后将匹配的第6行(即邮件:在上述情况下)修改为从文件-2获取的相应值abc@email.com。对文件-2中的所有值执行此操作。

如何使用sed或awk实现这一目标?我做了这个主要的不成功尝试。

 input=file-2
 a="sn: "
 b="mail: "
 while read -r line
 do
    read -r f1 f2  <<<"$line"
    c=$b$f2
    d=$a$f1
    sed -i 's/\($d\)\(.*\)/\1$c/' file-1
 done<"$input"

2 个答案:

答案 0 :(得分:2)

以下内容应该有效(如script.awk):

NR==FNR {
    m[$1]=$2
    next
}

$1=="cn:" { u=$2 }

$1=="mail:" {
    print "mail: " m[u]
    next
}

1

awk -f script.awk file-2 file-1运行。

NR==FNR位循环遍历第一个文件中的所有行(因为总看到的记录号NR与当前文件的记录号NR相同。在这样做的同时,它构建了一个关联数组/哈希映射用户名到电子邮件地址。

然后,脚本的其余部分会捕获最近看到的用户名($1=="cn:" bit) and stores that in a variable. When the script next sees a line that starts with邮件:(the $ 1 ==“mail:”位),它会打印出mail: <the saved email for the currently stored username>并继续前进。

最后的1只是用于打印当前行的awk简写(模式的操作默认为{print},任何计算为true的模式都将执行其操作)。任何非零的非空字符串值都可以代替1

答案 1 :(得分:1)

鉴于您的用户名 - &gt;电子邮件映射在名为emails.txt的文件中,以及此script.awk

NR == FNR { emails[$1] = $2; next }
$1 == "cn:" { username = $2; }
$1 == "mail:" { print $1, emails[username]; next }
1

您可以使用以下命令为映射文件和ldif文件运行此命令:

awk -f script.awk emails.txt file.ldif