8

我正在尝试解析测试文件。该文件具有以下格式的用户名、地址和电话:

Name: John Doe1
address : somewhere
phone: 123-123-1234

Name: John Doe2
address : somewhere
phone: 123-123-1233

Name: John Doe3
address : somewhere
phone: 123-123-1232

仅适用于近 10k 用户:) 我想做的是将这些行转换为列,例如:

Name: John Doe1                address : somewhere          phone: 123-123-1234
Name: John Doe2                address : somewhere          phone: 123-123-1233
Name: John Doe3                address : somewhere          phone: 123-123-1232

我更愿意在其中执行此操作,bash但如果您知道如何在 python 中执行此操作也很棒,那么包含此信息的文件位于 /root/docs/information.xml 中。任何提示或帮助将不胜感激。

4

11 回答 11

5

一种方法GNU awk

awk 'BEGIN { FS="\n"; RS=""; OFS="\t\t" } { print $1, $2, $3 }' file.txt

结果:

Name: John Doe1     address : somewhere     phone: 123-123-1234
Name: John Doe2     address : somewhere     phone: 123-123-1233
Name: John Doe3     address : somewhere     phone: 123-123-1232

请注意,我已将输出文件分隔符 ( OFS) 设置为两个制表符 ( \t\t)。您可以将其更改为您喜欢的任何字符或字符集。HTH。

于 2012-10-11T03:00:00.933 回答
3

用一个短Perl的单线:

$ perl -ne 'END{print "\n"}chomp; /^$/ ? print "\n" : print "$_\t\t"' file.txt

输出

Name: John Doe1         address : somewhere             phone: 123-123-1234
Name: John Doe2         address : somewhere             phone: 123-123-1233
Name: John Doe3         address : somewhere             phone: 123-123-1232
于 2012-10-11T03:02:17.933 回答
2

使用粘贴,我们可以加入文件中的行:

$ paste -s -d"\t\t\t\n" file
Name: John Doe1 address : somewhere     phone: 123-123-1234
Name: John Doe2 address : somewhere     phone: 123-123-1233
Name: John Doe3 address : somewhere     phone: 123-123-1232
于 2012-10-11T03:04:06.337 回答
1

这似乎基本上可以满足您的要求:

information = 'information'  # file path

with open(information, 'rt') as input:
    data = input.read()

data = data.split('\n\n')

for group in data:
    print group.replace('\n', '     ')

输出:

Name: John Doe1     address : somewhere     phone: 123-123-1234
Name: John Doe2     address : somewhere     phone: 123-123-1233
Name: John Doe3     address : somewhere     phone: 123-123-1232     
于 2012-10-11T03:02:57.907 回答
1

我知道你没有提到 awk,但它很好地解决了你的问题:

awk 'BEGIN {RS="";FS="\n"} {print $1,$2,$3}' data.txt
于 2012-10-11T03:06:58.063 回答
1

这里的大多数解决方案只是重新格式化您正在阅读的文件中的数据。也许这就是你想要的。

如果您确实要解析数据,请将其放入数据结构中。

Python中的这个例子:

data="""\
Name: John Doe2
address : 123 Main St, Los Angeles, CA 95002
phone: 213-123-1234

Name: John Doe1
address : 145 Pearl St, La Jolla, CA 92013
phone: 858-123-1233

Name: Billy Bob Doe3
address : 454 Heartland St, Mobile, AL 00103
phone: 205-123-1232""".split('\n\n')      # just a fill-in for your file
                                          # you would use `with open(file) as data:`

addr={}
w0,w1,w2=0,0,0             # these keep track of the max width of the field 
for line in data:
    fields=[e.split(':')[1].strip() for e in [f for f in line.split('\n')]]
    nam=fields[0].split()
    name=nam[-1]+', '+' '.join(nam[0:-1])
    addr[(name,fields[2])]=fields
    w0,w1,w2=[max(t) for t in zip(map(len,fields),(w0,w1,w2))]

现在您可以自由排序、更改格式、放入数据库等。

这将使用该数据打印您的格式,并排序:

for add in sorted(addr.keys()):
    print 'Name: {0:{w0}} Address: {1:{w1}} phone: {2:{w2}}'.format(*addr[add],w0=w0,w1=w1,w2=w2)

印刷:

Name: John Doe1      Address: 145 Pearl St, La Jolla, CA 92013   phone: 858-123-1233
Name: John Doe2      Address: 123 Main St, Los Angeles, CA 95002 phone: 213-123-1234
Name: Billy Bob Doe3 Address: 454 Heartland St, Mobile, AL 00103 phone: 205-123-1232

这是按姓氏排序的,字典键中使用的名字。

现在按区号排序打印它:

for add in sorted(addr.keys(),key=lambda x: addr[x][2] ):
    print 'Name: {0:{w0}} Address: {1:{w1}} phone: {2:{w2}}'.format(*addr[add],w0=w0,w1=w1,w2=w2)

印刷:

Name: Billy Bob Doe3 Address: 454 Heartland St, Mobile, AL 00103 phone: 205-123-1232
Name: John Doe2      Address: 123 Main St, Los Angeles, CA 95002 phone: 213-123-1234
Name: John Doe1      Address: 145 Pearl St, La Jolla, CA 92013   phone: 858-123-1233

但是,由于您在索引字典中有数据,您可以将其打印为表格,而不是按邮政编码排序:

# print table header
print '|{0:^{w0}}|{1:^{w1}}|{2:^{w2}}|'.format('Name','Address','Phone',w0=w0+2,w1=w1+2,w2=w2+2)
print '|{0:^{w0}}|{1:^{w1}}|{2:^{w2}}|'.format('----','-------','-----',w0=w0+2,w1=w1+2,w2=w2+2)
# print data sorted by last field of the address - probably a zip code
for add in sorted(addr.keys(),key=lambda x: addr[x][1].split()[-1]):
    print '|{0:>{w0}}|{1:>{w1}}|{2:>{w2}}|'.format(*addr[add],w0=w0+2,w1=w1+2,w2=w2+2)

印刷:

|      Name      |              Address               |    Phone     |
|      ----      |              -------               |    -----     |
|  Billy Bob Doe3|  454 Heartland St, Mobile, AL 00103|  205-123-1232|
|       John Doe1|    145 Pearl St, La Jolla, CA 92013|  858-123-1233|
|       John Doe2|  123 Main St, Los Angeles, CA 95002|  213-123-1234|
于 2012-10-11T16:44:04.857 回答
0

在 Python 中:

results = []
cur_item = None

with open('/root/docs/information') as f:
    for line in f.readlines():
        key, value = line.split(':', 1)
        key = key.strip()
        value = value.strip()

        if key == "Name":
            cur_item = {}
            results.append(cur_item)
        cur_item[key] = value

for item in results:
    # print item
于 2012-10-11T02:57:42.760 回答
0

您应该能够使用split()字符串上的方法来解析它:

line = "Name: John Doe1"
key, value = line.split(":")
print(key) # Name
print(value) # John Doe1
于 2012-10-11T02:59:06.997 回答
0

您可以遍历行并将它们打印在这样的列中 -

for line in open("/path/to/data"):
    if len(line) != 1:
        # remove \n from line's end and make print statement
        # skip the \n it adds in the end to continue in our column
        print "%s\t\t" % line.strip(),
    else:
        # re-use the blank lines to end our column
        print
于 2012-10-11T03:03:21.783 回答
0
#!/usr/bin/env python

def parse(inputfile, outputfile):
    dictInfo = {'Name':None, 'address':None, 'phone':None}
    for line in inputfile:
    if line.startswith('Name'):
        dictInfo['Name'] = line.split(':')[1].strip()
    elif line.startswith('address'):
        dictInfo['address'] = line.split(':')[1].strip()
    elif line.startswith('phone'):
        dictInfo['phone'] = line.split(':')[1].strip()
        s = 'Name: '+dictInfo['Name']+'\t'+'address: '+dictInfo['address'] \
            +'\t'+'phone: '+dictInfo['phone']+'\n'
        outputfile.write(s)

if __name__ == '__main__':
    with open('output.txt', 'w') as outputfile:
    with open('infomation.txt') as inputfile:
        parse(inputfile, outputfile)
于 2012-10-11T03:12:29.850 回答
0

使用sed.

cat input.txt | sed '/^$/d' | sed 'N; s:\n:\t\t:; N; s:\n:\t\t:'
  1. 第一个管道,sed '/^$/d',删除空行。
  2. 第二个管道 ,sed 'N; s:\n:\t\t:; N; s:\n:\t\t:'结合了这些线条。
姓名:John Doe1 地址:某处电话:123-123-1234
姓名:John Doe2 地址:某处电话:123-123-1233
姓名:John Doe3 地址:某处电话:123-123-1232
于 2012-10-11T04:30:21.800 回答