Создайте файл постфиксных псевдонимов из LDIF с помощью awk

Я хочу создать файл псевдонимов Postfix из LDIF-вывода ldapsearch.

Файл LDIF содержит записи примерно для 10 000 пользователей. У каждого пользователя есть хотя бы одна запись для атрибута proxyAddresses. Мне нужно создать псевдоним, соответствующий каждому proxyAddress, который соответствует условиям ниже. Созданные псевдонимы должны указывать на [email protected].

  • Тип — SMTP или smtp (без учета регистра).
  • Домен точно contoso.com

Я не уверен, что порядок атрибутов в файле LDIF согласован. Я не думаю, что могу предположить, что sAMAccountName всегда будет отображаться последним.

Пример входного файла

dn: CN=John Smith,OU=Users,DC=contoso,DC=com
proxyAddresses: SMTP:[email protected]
proxyAddresses: smtp:[email protected]
proxyAddresses: smtp:[email protected]
proxyAddresses: MS:ORG/ORGEXCH/JOHNSMITH
sAMAccountName: smith

dn: CN=Tom Frank,OU=Users,DC=contoso,DC=com
sAMAccountName: frank
proxyAddresses: SMTP:[email protected]
proxyAddresses: smtp:[email protected]
proxyAddresses: smtp:[email protected]
proxyAddresses: MS:ORG/ORGEXCH/TOMFRANK

Пример выходного файла

smith: [email protected]
John.Smith: [email protected]
frank: [email protected]
Tom.Frank: [email protected]

Идеальное решение

Я хотел бы увидеть решение с использованием awk, но приемлемы и другие методы. Вот качества, которые наиболее важны для меня, по порядку:

  1. Просто и читабельно. Самодокументирование лучше, чем однострочники.
  2. Эффективный. Это будет использовано тысячи раз.
  3. Идиоматический. Было бы неплохо сделать это "неправильным способом", если бы это не ставило под угрозу первые две цели.

Что я пробовал

Мне удалось начать с этого, но я изо всех сил пытаюсь понять тонкости awk.

  • Я попытался использовать csplit для создания отдельных файлов для каждой записи в выводе LDIF, но это кажется расточительным, поскольку в конце мне нужен только один файл.
  • Я попытался установить RS="" в awk, чтобы получить полные записи, а не отдельные строки, но тогда я не знал, что делать дальше.
  • Я попытался использовать awk, чтобы разбить большой файл LIDF на отдельные файлы для каждой записи, а затем обработать их с помощью другого сценария оболочки, но это казалось расточительным.

person Nic    schedule 03.08.2013    source источник


Ответы (2)


Вот скрипт gawk, который вы можете запустить следующим образом: gawk -f ldif.awk yourfile.ldif Обратите внимание: многосимвольное значение `RS' является расширением gawk.

$ cat ldif.awk
BEGIN {
    RS = "\n\n"  # Record separator: empty line
    FS = "\n"    # Field separator: newline
}

# For each record: loop twice through fields
{
    # Loop #1 identifies the sAMAccountName
    for (i = 1; i <= NF; i++) {
        if ($i ~ /^sAMAccountName: /) {
            sAN = substr($i, 17)
            break
        }
    }

    # Loop #2 prints output lines
    for (i = 1; i <= NF; i++) {
        if (tolower($i) ~ /smtp:.*@contoso.com$/) {
            split($i, n, ":|@")
            print n[3] ": " sAN "@other.domain"
        }
    }
}
person Hermann    schedule 04.08.2013
comment
Спасибо, это дает именно те результаты, которые мне нужны! - person Nic; 07.08.2013

Вот способ сделать это с помощью стандартного awk.

# Display the postfix alias(es) for the previous user (if any)
function dump() {
  for(i in id) printf("%s: %[email protected]\n",id[i],an);
  delete id;
}
# store all email names for that user in the id array
/^proxyAddresses:.[Ss][Mm][Tt][Pp]:.*@contoso.com/ {gsub(/^.*:/,"");gsub(/@.*$/,"");id[i++]=$0}
# store the account name
/^sAMAccountName:/ {an=$2};
# When a new record is found, process the previous one
/^dn:/ {dump()}
# Process the last record
END {dump()}
person jlliagre    schedule 04.08.2013
comment
Это почти сработало для меня, но мне нужно было пропустить все адреса, отличные от SMTP. Мне нравится, как это очень лаконично, хотя. - person Nic; 07.08.2013
comment
Код исправлен, я упускаю из виду требование smtp. - person jlliagre; 07.08.2013