【问题标题】:Zimbra zmprov formatted file to csv and ldifZimbra zmrov 格式化文件到 csv 和 ldif
【发布时间】:2019-07-12 21:57:57
【问题描述】:

我正在学习 python,我的第一个任务是将 Zimbra zmprov 格式化文件转换为 csvldif

由于我不知道完成任务的 python 内置函数,所以我走了很长的路,遍历行和打印。

如果你们能告诉我如何正确地做,我将不胜感激。

这是输入的zmp_file,要转换成csv和ldif

ca user1@domain.com.br      ''
ma user1@domain.com.br cn   'User One'
ma user1@domain.com.br cpf  ''
ma user1@domain.com.br l    'Porto Alegre'

ca user2@domain.com.br      ''
ma user2@domain.com.br cn   'User Two'
ma user2@domain.com.br cpf  '0123456789'
ma user2@domain.com.br l    ''

所需的 .csv 输出(字段的顺序并不重要)

mail,cn,cpf,l
user1@domain.com.br,"User One",,"Porto Alegre"
user2@domain.com.br,"User Two",0123456789,

以及所需的 .ldif 输出(字段的顺序并不重要)

dn:   'uid=user1@domain.com.br'
cn:   'User One'
l:    'Porto Alegre'
mail: 'user1@domain.com.br'

dn:   'uid=user2@domain.com.br'
cn:   'User Two'
cpf:  '0123456789'
mail: 'user2@domain.com.br'

我能走多远:

with zmp_file as input_file
    for line in input_file:
        if line.startswith('ca'):
            mail = line.split()[1]
            print "dn: uid={0}".format(mail)
            print "mail: {0}".format(mail)
        elif line.startswith('ma'):
            words = shlex.split(line)[-2:]
            print "{0}: {1}".format(words[0], words[1])
        else:
            print

【问题讨论】:

  • 你能分享zmprov输入文件并显示预期的输出格式吗?
  • 所以基本上zmp_file文件是一个文本?

标签: python csv zimbra ldif


【解决方案1】:

您可以使用regexpandaszmprov 转换为csvldif

import re
import pandas as pd

with open('file.txt', 'r') as f:
    data = f.read()

mail = re.findall('ca (\S+)', data)
cn = re.findall('cn +(.*)', data)
cpf = re.findall('cpf + (.*)', data)
l = re.findall('l + (.*)', data)

df = pd.DataFrame({'mail': mail, 'cn': cn, 'cpf': cpf, 'l': l})
df.to_csv('file.csv', sep=',', encoding='utf-8', index=False)

with open('file.ldif', 'w') as f:
    for m_, cn_, cpf_, l_ in zip(mail, cn, cpf, l):
        if re.findall('\w+', l_):
            f.write("""dn:   'uid={m}'\ncn:   {cn}\nl:    {l}\nmail: '{m}'\n\n""".format(m=m_, cn=cn_, l=l_))
        elif cpf_:
            f.write("""dn:   'uid={m}'\ncn:   {cn}\ncpf:  {cpf}\nmail: '{m}'\n\n""".format(m=m_, cn=cn_, cpf=cpf_))

输出file.csv:

mail,cn,cpf,l
user1@domain.com.br,'User One','','Porto Alegre'
user2@domain.com.br,'User Two','0123456789',''

输出file.ldif:

dn:   'uid=user1@domain.com.br'
cn:   'User One'
l:    'Porto Alegre'
mail: 'user1@domain.com.br'

dn:   'uid=user2@domain.com.br'
cn:   'User Two'
cpf:  '0123456789'
mail: 'user2@domain.com.br'

【讨论】:

  • 因此,如果未定义变量,则在 CSV 中设置空值。请参阅我的更新答案。
  • 但是我事先不知道要使用正则表达式搜索的字段名称,如果我有 90 个字段而不是 5 个呢?我应该把它们都写在脚本里吗?
  • 请使用该信息更新您的问题并显示完整的输入格式。问题描述不好真的很难解决。
【解决方案2】:

好的。明白了。

我知道这不是 codereview.stackexchange.com,但如果有人有 cmets,我来这里学习。

#!/usr/bin/env python

import csv
import os
import shlex
import sys
from ldif import LDIFParser, LDIFWriter

def zmp_to_csv_and_ldif(zmp_file):

    all_attrs = set()
    data      = {}
    records   = {}

    with zmp_file as input_file:
        for line in input_file:
            if line.startswith('ca'):
                cmd, mail, pwd       = line.split()
                data['mail']         = mail
                data['userpassword'] = pwd
                records[mail]        = data
                all_attrs.update(['mail','userpassword'])
            elif line.startswith('ma'):
                cmd, mail, attr, value = shlex.split(line)
                data[attr]             = value
                records[mail]          = data
                all_attrs.add(attr)
            else:
                data = {}

    with open('/tmp/rag-parsed.csv', 'w') as output_file:
        csv_writer = csv.DictWriter(output_file, fieldnames=all_attrs, extrasaction='ignore', lineterminator='\n')
        csv_writer.writeheader()
        for mail, data in sorted(records.items()):
            csv_writer.writerow(data)

    with open('/tmp/rag-parsed.ldif', 'w') as output_file:
        b64_attrs   = map(str.lower, ['jpegPhoto', 'userPassword'])
        ldif_writer = LDIFWriter(output_file, base64_attrs=b64_attrs, cols=999)
        for mail, data in sorted(records.items()):
            dn = "uid={0}".format(mail)
            data_in_ldap_fmt = dict([k, v.split('\n')] for k, v in data.items() if v)
            ldif_writer.unparse(dn, data_in_ldap_fmt)

【讨论】:

    猜你喜欢
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-19
    • 2020-10-28
    • 1970-01-01
    相关资源
    最近更新 更多