2014-01-08 5 views
1

Мне нужно изменить файл, содержащий огромное количество ldifs. В основном структура файла похожа на это. Я называю этот файл файлом-1.Изменение n-й строки после сопоставления шаблону

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

cn: username2 
... 

Поэтому мне нужно совместить cn: example1, а затем изменить соответствующую почту: i.e 6-я строка после сопоставления. У меня есть еще один файл с именем file-2, из которого я собираюсь изменить новое значение. Файл-2 имеет такой синтаксис.

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

Так что я хочу сделать вот так. Возьмите username1 из файла-2, сопоставьте его в файле-1, если совпадение найдено, затем измените 6-ю строчку из соответствия (например, почта: в приведенном выше случае) на соответствующее значение [email protected], взятое из файла-2. Выполнение этого для всех значений в файле-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:'. Если кто-то изменит формат файла-1, чтобы было больше строк, или строки находятся в другом порядке, ваш код не будет работать и должен быть изменен. Или, что еще хуже, количество строк может даже не быть известно во время компиляции, если некоторые строки являются необязательными или если части после ':' разрешено содержать символы новой строки. Вместо этого вы должны написать код, который найдет первую строку 'mail:' после строки 'cn:'. –

+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: <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

Спасибо ..! Это тоже сработало. –

Смежные вопросы