Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 替换以txt制表符分隔的大型文件中第一行的文本_Python_Perl_File_Vbscript - Fatal编程技术网

Python 替换以txt制表符分隔的大型文件中第一行的文本

Python 替换以txt制表符分隔的大型文件中第一行的文本,python,perl,file,vbscript,Python,Perl,File,Vbscript,我有一个巨大的文本文件(19GB大小);这是一个包含变量和观察值的遗传数据文件。 第一行包含变量名,其结构如下: id1.var1 id1.var2 id1.var3 id2.var1 id2.var2 id2.var3 我需要交换id1,id2等。对于另一个文本文件中的相应值(此文件约有7k行),ID不按任何特定顺序排列,其结构如下: oldId newIds id1 rs004 id2 rs135 我在谷歌上做了一些搜索,但找不到一种语言可以做到以下几点: 读第一行 用新ID替换ID

我有一个巨大的文本文件(19GB大小);这是一个包含变量和观察值的遗传数据文件。
第一行包含变量名,其结构如下:

id1.var1 id1.var2 id1.var3 id2.var1 id2.var2 id2.var3 
我需要交换id1,id2等。对于另一个文本文件中的相应值(此文件约有7k行),ID不按任何特定顺序排列,其结构如下:

oldId newIds
id1 rs004
id2 rs135
我在谷歌上做了一些搜索,但找不到一种语言可以做到以下几点:

  • 读第一行
  • 用新ID替换ID
  • 从原始文件中删除第一行,并将其替换为新文件
  • 这是一个好方法还是有更好的方法?
    实现这一目标的最佳语言是什么?

    我们有在python、vbscipt和Perl方面有经验的人员。

    这应该很容易。我会使用Python,因为我是Python迷。大纲:

    • 读取映射文件并保存映射(在Python中,使用字典)

    • 一次读取一行数据文件,重新映射变量名称,然后输出编辑的行

    您确实无法在位编辑文件。。。嗯,如果每个新变量名的长度总是与旧名称的长度完全相同的话,我想你可以这样做。但为了编程的方便性和运行时的安全性,最好总是编写一个新的输出文件,然后删除原始文件。这意味着您在运行此操作之前需要至少20 GB的可用磁盘空间,但这应该不是问题

    下面是一个Python程序,它演示了如何执行此操作。我使用您的示例数据制作测试文件,这似乎是可行的

    #!/usr/bin/python
    
    import re
    import sys
    
    try:
        fname_idmap, fname_in, fname_out = sys.argv[1:]
    except ValueError:
        print("Usage: remap_ids <id_map_file> <input_file> <output_file>")
        sys.exit(1)
    
    # pattern to match an ID, only as a complete word (do not match inside another id)
    # match start of line or whitespace, then match non-period until a period is seen
    pat_id = re.compile("(^|\s)([^.]+).")
    
    idmap = {}
    
    def remap_id(m):
        before_word = m.group(1)
        word = m.group(2)
        if word in idmap:
            return before_word + idmap[word] + "."
        else:
            return m.group(0)  # return full matched string unchanged
    
    def replace_ids(line, idmap):
        return re.sub(pat_id, remap_id, line)
    
    with open(fname_idmap, "r") as f:
        next(f)  # discard first line with column header: "oldId newIds"
        for line in f:
            key, value = line.split()
            idmap[key] = value
    
    with open(fname_in, "r") as f_in, open(fname_out, "w") as f_out:
        for line in f_in:
            line = replace_ids(line, idmap)
            f_out.write(line)
    
    #/usr/bin/python
    进口稀土
    导入系统
    尝试:
    fname_idmap,fname_in,fname_out=sys.argv[1:]
    除值错误外:
    打印(“用法:重新映射ID”)
    系统出口(1)
    #模式匹配一个ID,仅作为一个完整的单词(在另一个ID内不匹配)
    #匹配行或空格的开头,然后匹配非句点,直到看到句点为止
    pat_id=re.compile(“(^|\s)([^.]+)”)
    idmap={}
    def重新映射id(m):
    前单词=m.组(1)
    word=m.组(2)
    如果idmap中有单词:
    返回在\u word+idmap[word]+”之前
    其他:
    返回m.group(0)#返回完全匹配的字符串不变
    def replace_ID(行,idmap):
    返回重新分配(分配id、重新映射id、行)
    将open(fname_idmap,“r”)作为f:
    下一步(f)#放弃列标题为“oldId newIds”的第一行
    对于f中的行:
    key,value=line.split()
    idmap[键]=值
    以open(fname_in,“r”)作为f_in,open(fname_out,“w”)作为f_out:
    对于f_in中的行:
    line=替换id(line,idmap)
    f_out.写入(行)
    
    整个“替换”过程在几乎任何语言中都是可能的(我对Python和Perl很确定),只要替换行的长度与原始行的长度相同,或者可以通过填充空格使其相同(否则,您必须重写整个文件)

    打开文件进行读写(
    w+
    模式),读取第一行,准备新行,
    seek
    到文件中的位置0,写入新行,关闭文件。

    我建议您使用该模块,它将文本文件中的行映射到一个Perl数组,并使头文件后面的行的重写成为一项简单的工作

    这个程序演示了。它首先将所有旧/新ID读入一个散列,然后使用
    Tie::file
    映射数据文件。使用替换修改文件的第一行(在
    $file[0]
    中),然后解开数组以重写和关闭文件

    您需要更改我使用的文件名。还要注意的是,我假设ID总是“单词”字符(字母数字加下划线),后跟一个点,并且没有空格。当然,在修改文件之前,您需要备份文件,并且在更新真实文件之前,您应该在较小的文件上测试程序

    use strict;
    use warnings;
    
    use Tie::File;
    
    my %ids;
    open my $fh, '<', 'newids.txt' or die $!;
    while (<$fh>) {
      my ($old, $new) = split;
      $ids{$old} = $new;
    }
    
    tie my @file, 'Tie::File', 'datafile.txt' or die $!;
    $file[0] =~ s<(\w+)(?=\.)><$ids{$1} // $1>eg;
    untie @file;
    
    使用严格;
    使用警告;
    使用Tie::文件;
    我的%id;
    
    打开我的$fh,'如果“id1”=>“rs004”,它可能不起作用。所以这可能是编写新文件的唯一方法。谢谢。我现在正在运行一个Python代码,它实现了您的建议。ID的长度不同,需要重写文件。我在windows环境中,运行可能需要几个小时。我希望它能起作用。非常感谢!我将向我的程序员展示这段代码。谢谢