【问题标题】:changing a character of columns of a large file更改大文件列的字符
【发布时间】:2014-04-20 02:44:50
【问题描述】:

我必须用另一个文件的相应列替换大文件的每个(备用)行的第 n 个字符。例如,我每 5 个字符更改一次。

文件1:

 >chr1:101842566-101842576
  CCTCAACTCA
 >chr1:101937281-101937291
 GAATTGGATA
 >chr1:101964276-101964286
 AAAAAATAGG
 >chr1:101972950-101972960
 ggctctcatg
 >chr1:101999969-101999979
 CATCATGACG

文件2:

 G
 A
 T
 A
 C

输出:

 >chr1:101842566-101842576
 CCTCGACTCA
 >chr1:101937281-101937291
 GAATAGGATA
 >chr1:101964276-101964286
 AAAATATAGG
 >chr1:101972950-101972960
 ggctAtcatg
 >chr1:101999969-101999979
 CATCCTGACG

每个(备用)行中的字符数可能很大。而且行数也很大。如何有效地做到这一点?

【问题讨论】:

    标签: string shell sed awk


    【解决方案1】:

    这是awk的一种方式:

    awk 'NR==FNR{a[NR]=$1;next}!/^>/{$1=substr($1,1,n-1) a[++i] substr($1,n+1)}1' n=5 f2 f1
    

    说明:

    • 我们遍历第二个文件并将其存储在以行号为索引的数组中。
    • 在内存中加载第二个文件后,我们将移至第二个文件。
    • 我们查找不以> 开头的行。
    • 找到后,我们替换数组中的值。我们通过使用substr 函数来做到这一点。
    • 定义的变量n允许你修改第n个字符
    • 对于没有> 的行,我们按原样使用1 打印它们,这是默认的 打印。
    • 此解决方案假定文件格式如上所示。也就是说,第一个文件将始终以> 开头,后跟要更改的行。第二个文件的替换将按照看到的顺序进行。

    演示:

    每 5 个字符:

    $ awk 'NR==FNR{a[NR]=$1;next}!/^>/{$1=substr($1,1,n-1) a[++i] substr($1,n+1)}1' n=5 f2 f1
    >chr1:101842566-101842576
    CCTCGACTCA
    >chr1:101937281-101937291
    GAATAGGATA
    >chr1:101964276-101964286
    AAAATATAGG
    >chr1:101972950-101972960
    ggctAtcatg
    >chr1:101999969-101999979
    CATCCTGACG
    

    每第三个字符:

    $ awk 'NR==FNR{a[NR]=$1;next}!/^>/{$1=substr($1,1,n-1) a[++i] substr($1,n+1)}1' n=3 f2 f1
    >chr1:101842566-101842576
    CCGCAACTCA
    >chr1:101937281-101937291
    GAATTGGATA
    >chr1:101964276-101964286
    AATAAATAGG
    >chr1:101972950-101972960
    ggAtctcatg
    >chr1:101999969-101999979
    CACCATGACG
    

    【讨论】:

      【解决方案2】:

      这就是我使用 perl 的方式。首先将 file2 的所有内容读入一个数组,然后遍历该数组,从 file1 读取两行和两行,打印第一行未修改,然后更改第二行的第 5 个字符:

      #!/usr/bin/perl
      use strict;
      use warnings;
      use diagnostics;
      #use Data::Printer;
      
      # Read all of file2
      
      my $lines;
      
      open(FILE, $ARGV[1]);
      {
          local $/;
          $lines = <FILE>;
      }
      close(FILE);
      
      my @new_chars = split(/\n/, $lines);
      
      # Read and process file1
      
      open(FILE, $ARGV[0]);
      
      foreach my $new_char (@new_chars) {
          # >chr1:101842566-101842576
          my $line = <FILE>;
          print $line;
          #  CCTCAACTCA
          $line = <FILE>;
          $line =~ s/^(....)./$1$new_char/; # Replace 5th character
          print $line;
      }
      
      close(FILE);
      

      【讨论】:

        【解决方案3】:

        您可以在 Python 中使用 mmap 就地替换文件中的列:

        #!/usr/bin/env python3
        """Replace inplace a column of a large file.
        
        Usage:
            $ ./replace-inplace file1 file2 5
        """
        import sys
        from mmap import ACCESS_WRITE, mmap
        
        def main():
            ncolumn = int(sys.argv[3]) - 1 # 1st column is 1
            with open(sys.argv[1], 'r+b') as file1:
                with mmap(file1.fileno(), 0, access=ACCESS_WRITE) as mm:
                    with open(sys.argv[2], 'rb') as file2:
                        while True:
                            mm.readline()   # ignore every other line
                            pos = mm.tell() # remember current position
                            if not mm.readline(): # EOF
                                break
                            replacement = file2.readline().strip()[0]
                            mm[pos + ncolumn] = replacement # replace the column
        
        main()
        

        假设您正在用一个字节替换一个字节,即文件中没有内容被移动。

        【讨论】:

          【解决方案4】:

          这可能对你有用(GNU sed、paste 和 cat):

          cat file1 | paste -d\\n\\t\\n - file2 - | sed -r 's/^(.)\t(.{4})./\2\1/' >file3
          

          将file2中的数据嵌入到file1中,然后重新排列。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-01-10
            • 2020-03-13
            • 1970-01-01
            • 1970-01-01
            • 2013-12-07
            • 2021-07-24
            相关资源
            最近更新 更多