以下是Python中的解决方案。我已经在我制作的一个小假文件上进行了测试。我认为即使是一个大文件,这个速度也是可以接受的,因为大部分工作将由Python内部的C代码完成。我认为这是一个令人愉快且易于理解的程序;我更喜欢Python到Perl。
import sys
s_usage = """\
Usage: csplit <filename>
Splits input file by columns, writes column 2 to file based on chromosome from column 4."""
if len(sys.argv) != 2 or sys.argv[1] in ("-h", "--help", "/?"):
sys.stderr.write(s_usage + "\n")
sys.exit(1)
# replace these with the actual patterns, of course
lst_pat = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y'
]
d = {}
for s_pat in lst_pat:
# build a dictionary mapping each pattern to an open output file
d[s_pat] = open("my_out_file_" + s_pat, "wt")
if False:
# if the patterns are unsuitable for filenames (contain '*', '?', etc.) use this:
for i, s_pat in enumerate(lst_pat):
# build a dictionary mapping each pattern to an output file
d[s_pat] = open("my_out_file_" + str(i), "wt")
for line in open(sys.argv[1]):
# split a line into words, and unpack into variables.
# use '_' for a variable name to indicate data we don't care about.
# s_data is the data we want, and s_pat is the pattern controlling the output
_, s_data, _, s_pat, _ = line.split()
# use s_pat to get to the file handle of the appropriate output file, and write data.
d[s_pat].write(s_data + "\n")
# close all the output file handles.
for key in d:
d[key].close()
编辑:这里有一点关于这个程序的更多信息,因为它似乎你会使用它。
所有的错误处理都是隐含的。如果发生错误,Python将“引发异常”,从而终止处理。例如,如果其中一个文件无法打开,该程序将停止执行,Python将打印一个回溯,显示哪一行代码导致异常。我可以用“try/except”块封装关键部分来捕捉错误,但对于一个简单的程序,我没有看到任何意义。
这很微妙,但有一个检查,看看输入文件的每一行中是否只有五个单词。当这段代码解开一行时,它会将它变成五个变量。 (变量名称“_”是一个合法的变量名称,但Python社区有一个惯例将它用于你并不真正关心的变量。)如果Python中没有完全五个单词,则Python会引发异常输入行以解压缩为五个变量。如果你的输入文件有时可能有四个单词,或者六个或更多,你可以修改程序不会引发异常;将主循环更改为:
for line in open(sys.argv[1]):
lst = line.split()
d[lst[3]].write(lst[1] + "\n")
这会将行拆分为单词,然后仅将整个单词列表分配到单个变量lst中。所以这一行代码并不关心有多少单词在线上。然后下一行索引到列表中以获取值。由于Python使用0索引列表以开始,因此第二个字是lst[1]
,第四个字是lst[3]
。只要列表中至少有四个单词,该行代码也不会引发异常。
当然,如果行中的第四个单词不在文件句柄的字典中,Python也会引发异常。那会停止处理。下面是如何使用“try/except”块来处理这个问题的一些示例代码:
for line in open(sys.argv[1]):
lst = line.split()
try:
d[lst[3]].write(lst[1] + "\n")
except KeyError:
sys.stderr.write("Warning: illegal line seen: " + line)
祝您的项目顺利。
编辑:@larelogio指出这段代码不符合AWK代码。 AWK代码有一个额外的循环,我不明白。这里是Python代码做同样的事情:
for line in open(sys.argv[1]):
lst = line.split()
n = int(lst[1])
for i in range(n, n+53):
d[lst[3]].write(i + "\n")
而这是另一种方式来做到这一点。这可能会快一点,但我没有测试过,所以我不确定。
for line in open(sys.argv[1]):
lst = line.split()
n = int(lst[1])
s = "\n".join(str(i) for i in range(n, n+53))
d[lst[3]].write(s + "\n")
这建立一个单一的字符串与所有的数字写入,然后写入一个块。与调用.write()
53次相比,这可以节省时间。
什么时候?可能提供一些您希望完成的范围?解析10GB的文本是一项相当大的工作。 – GrayWizardx 2009-12-17 02:01:00
请在可能的位置显示示例文件 – ghostdog74 2009-12-17 03:03:30