2012-10-11 15 views
8

Próbuję przeanalizować plik testowy. plik ma nazwę użytkownika, adres i numer telefonu w następującym formacie:Dane pliku tekstowego analizujące wiersze i dane wyjściowe jako kolumny

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 

Tylko dla prawie 10k użytkowników:) co chciałbym zrobić, to przekształcić tych wierszy do kolumn, na przykład:

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 

Wolałbym to zrobić w bash, ale jeśli wiesz, jak to zrobić w pythonie, który również byłby świetny, plik zawierający te informacje znajduje się w katalogu/root/docs/information. Wszelkie wskazówki lub pomoc będą mile widziane.

+2

Czego próbowałeś? – nneonneo

+0

Dobre początkowe pytanie, @tafiela. Ale nie zapomnij podać w następnych pytaniach, co próbujesz zrobić. – Yamaneko

+0

Czy adres jest rzeczywiście tylko jeden wiersz za dwukropkiem? –

Odpowiedz

5

Jednym ze sposobów, z GNU awk:

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

Wyniki:

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 

Należy pamiętać, że ustawiłem separator plików wyjściowych (OFS) na dwa znaki tabulacji (\t\t). Możesz to zmienić na dowolną postać lub zestaw znaków, które chcesz. HTH.

+0

+1 - pokonałeś mnie do ponczu. –

+0

Co 'RS' ma? – Yamaneko

+1

@VictorHugo: 'RS' jest skrótem od separatora rekordów. Domyślnie 'RS' jest ustawione na' \ n' lub znak nowej linii. Umożliwia to 'awk' przetwarzanie pliku wiersz po linii. Kiedy ustawimy go na nic (lub '' "'), faktycznie zmieniamy 'awk' definicję linii. Ponieważ każdy z rekordów jest oddzielony pustymi wierszami, ustawienie 'RS =" "' sprawia, że ​​jest to łatwe rozwiązanie. HTH. – Steve

0

W Pythonie:

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

Powinieneś sprecyzować język;) –

+0

@sputnick Nie jestem całkiem Rozumiem co masz na myśli –

+0

Po prostu powiedz język: To jest Python. – Matthias

0

powinny być zdolne do analizowania tego stosując metodę split() na sznurku:

line = "Name: John Doe1" 
key, value = line.split(":") 
print(key) # Name 
print(value) # John Doe1 
3

Z krótkim Perl jedną wkładką:

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

OUTPUT

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 
1

Wydaje się to zrobić w zasadzie to, co chcesz:

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', '  ') 

wyjściowa:

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  
0

Można iteracyjne nad liniami i wydrukować je w kolumnach tak -

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 
2

Używanie pasty, możemy dołączyć linie w pliku:

$ 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 
+0

Nie tak dobrze sformatowany =) –

+0

@sputnick Prawda, ale to nie jest trudne. Istnieje mnóstwo narzędzi do rozbudowy kart. –

+0

Tak, ale w tym przypadku potrzebujesz 2 rur;) –

1

wiem, że nie wspominając awk, ale to rozwiązuje problem ładnie:

awk 'BEGIN {RS="";FS="\n"} {print $1,$2,$3}' data.txt 
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) 
0

Rozwiązanie przy użyciu sed.

cat input.txt | sed '/^$/d' | sed 'N; s:\n:\t\t:; N; s:\n:\t\t:' 
  1. pierwszej rury, sed '/^$/d', usuwa puste linie.
  2. Druga rura, sed 'N; s:\n:\t\t:; N; s:\n:\t\t:', łączy w sobie linie.
 
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 
1

Większość z rozwiązaniami tutaj są tylko formatowanie danych w pliku, który czytasz. Może to wszystko, czego chcesz.

Jeśli rzeczywiście chcesz przeanalizować dane, umieść je w strukturze danych.

Ten przykład w Pythonie:

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))] 

Teraz masz wolność do sortowania, zmień format, umieścić w bazie danych, itp

Wypisuje format z tymi danymi, sortowane:

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) 

Wydruki:

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 

To jest posortowane według nazwiska, imienia użytego w kluczu dyktującym.

teraz wydrukować posortowane według numerem kierunkowym:

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) 

Prints:

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 

Ale skoro masz dane w indeksowanej słownika można wydrukować w postaci tabeli zamiast posortowane według Kod pocztowy:

# 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) 

Wydruki:

|  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| 
Powiązane problemy