2014-01-08 66 views
1

我需要修改包含大量ldif的文件。基本上文件的结构就是这样。我把这个文件称为file-1。匹配模式后修改第n行

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

cn: username2 
... 

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

username1 [email protected] 
username2 [email protected] 
... 

所以我想这样做。如果找到匹配项,则从file-2取得username1并将其与file-1匹配,然后将匹配的第6行(即上面的情况中的mail)修改为从file-2取得的对应值[email protected]。为文件-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" 
+0

您只能使用sed和awk?否则,你总是可以试试看Perl – delephin

+0

你不应该通过计算'cn:'之后的行数来做到这一点。如果有人更改了file-1的格式以便有更多的行,或者行的顺序不同,那么代码将会失败并需要修改。或者更糟糕的是,如果某些行是可选的,或者':'之后的部分允许包含换行符,编译时甚至可能不会知道行数。相反,你应该编写在你的'cn:'行之后找到第一个'mail:'行的代码。 –

+0

@delephin其实我对perl知之甚少。我知道一些基本的sed和awk。 –

回答

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

+0

谢谢.. !!它为我工作。你可以给我一些解释,如果可能的话,这个脚本如何工作?我在学习sed&awk,只是想知道这是如何工作的。 –

1

鉴于您的用户名 - >电子邮件映射在一个名为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 
+0

谢谢..!这也工作。 –