2014-01-08 65 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

謝謝..!這也工作。 –