转换文件格式

时间:2015-08-18 02:53:10

标签: python unix formatting

我有以下示例文件(a),我想使用Unix或Python命令将其转换为示例文件(b)。我的实际文件要大得多(几GB)。

(A):

Sol_00000001    H2O2    KNMO4   NaCl
Sol_00000002    NaCl    NaCl
Sol_00000003    KOCl    NHO2    NHO2
Sol_00000004    H2O2
Sol_00000005    KNMO4
Sol_00000006    NaCl
Sol_00000007    KOCl
Sol_00000008    NHO2
Sol_00000009    H2O2    NaCl    KOCl    NHO2    KNMO4

(B):

NaCl    Sol_00000001    Sol_00000002    Sol_00000006    Sol_00000009
KOCl    Sol_00000003    Sol_00000007    Sol_00000009
H2O2    Sol_00000001    Sol_00000004    Sol_00000009
NHO2    Sol_00000003    Sol_00000008    Sol_00000009
KNMO4   Sol_00000001    Sol_00000005    Sol_00000009

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:2)

我将提供3种解决方案 - 在Awk,Perl和Python 2中。

awk中

这是一个运行awk

的shell脚本
#!/bin/sh

awk '{ for (i = 2; i <= NF; i++) list[$i] = list[$i] "  " $1 }
     END { for (i in list) printf "%-7s  %s\n", i, list[i] }' "$@"

的Perl

#!/usr/bin/env perl
use strict;
use warnings;

my %list = ();

while (<>)
{
    my ($chem, @soln) = split;
    push @{$list{$_}}, $chem foreach (@soln);
}

for my $key (sort { lc($a) cmp lc($b) } keys %list)
{
    printf "%-7s  %s\n", $key, join('  ', @{$list{$key}});
}

Python 2

#!/usr/bin/env python

import fileinput

list = {}

for line in fileinput.input():
    bits = line.split()
    for i in range(1, len(bits)):
        if bits[i] not in list:
            list[bits[i]] = []
        list[bits[i]].append(bits[0])

for key in sorted(list.keys(), key = str.lower):
    print "%-7s  %s" % (key, '  '.join(list[key]))

示例输出

$ sh so.32062773.sh so.32062773.data
NaCl       Sol_00000001  Sol_00000002  Sol_00000002  Sol_00000006  Sol_00000009
H2O2       Sol_00000001  Sol_00000004  Sol_00000009
KNMO4      Sol_00000001  Sol_00000005  Sol_00000009
KOCl       Sol_00000003  Sol_00000007  Sol_00000009
NHO2       Sol_00000003  Sol_00000003  Sol_00000008  Sol_00000009
$ perl so.32062773.pl so.32062773.data
H2O2     Sol_00000001  Sol_00000004  Sol_00000009
KNMO4    Sol_00000001  Sol_00000005  Sol_00000009
KOCl     Sol_00000003  Sol_00000007  Sol_00000009
NaCl     Sol_00000001  Sol_00000002  Sol_00000002  Sol_00000006  Sol_00000009
NHO2     Sol_00000003  Sol_00000003  Sol_00000008  Sol_00000009
$ python so.32062773.py so.32062773.data
H2O2     Sol_00000001  Sol_00000004  Sol_00000009
KNMO4    Sol_00000001  Sol_00000005  Sol_00000009
KOCl     Sol_00000003  Sol_00000007  Sol_00000009
NaCl     Sol_00000001  Sol_00000002  Sol_00000002  Sol_00000006  Sol_00000009
NHO2     Sol_00000003  Sol_00000003  Sol_00000008  Sol_00000009
$

awk不会尝试对键进行排序。将输出传递给sort -f以获得与Perl和Python相同的不区分大小写的排序输出是可行的。

答案 1 :(得分:1)

如果您的源数据位于ch_source.txt中,则此脚本将以上述格式创建ch_dst.txt。但它会在进程中使用大量内存,因为在创建输出文件之前必须存储所有数据。

这是一个Python 2脚本。 Python 3脚本必须使用字节才能节省空间,并且使用items代替iteritems

通过更多研究,您将了解如何在命令行上传递文件名,而不是将其硬编码到脚本中。

#! /usr/bin/env python2

import collections

def translate(srcf, dstf):
    by_chem = collections.defaultdict(list)

    with open(srcf, 'rb') as f:
        for line in f:
            values = line.split()
            if not values:
                continue
            soln = values.pop(0)
            for chem in values:
                by_chem[chem].append(soln)
    with open(dstf, 'wb') as f:
        for chem, solns in sorted(by_chem.iteritems()):
            f.write('%s\t%s\n' % (chem, '\t'.join(solns)))

translate('ch_source.txt', 'ch_dst.txt')

答案 2 :(得分:0)

基本上,您需要读取文件的每一行,将该行拆分为其组成单词,然后为每个分子记录它发生的解决方案。在python中,用于存储此信息的最自然的数据结构是一个字典。键是分子,值是含有分子的溶液列表。一旦构建了dict,就必须将每个条目写入文件。

这应该足以让你入门。小心一点,如果你无法解决问题,请回过头来回答。