穿插两个不同文件的行

时间:2012-02-17 14:58:11

标签: python sed awk

我必须做一个简单的任务,但我不知道该怎么做而且我已经赌了。我需要每4行散布两个不同文件的行:

文件1:

1
2
3
4
5
6
7
8
9
10
11
12

文件2:

A
B
C
D
E
F
G
H
I
J
K
L

期望的结果:

1
2
3
4
A
B
C
D
5
6
7
8
E
F
G
H
9
10
11
12
I
J
K
L

我正在寻找sed,awk或python脚本或任何其他bash命令。

感谢您的时间!!

我尝试使用特定的python库来识别每个文件的4行模块。但它不起作用,现在我试图在没有这个库的情况下这样做,但不知道如何。

import sys
from Bio import SeqIO
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord


def main(forward,reverse):

    for F, R in zip ( SeqIO.parse(forward, "fastq"), SeqIO.parse(reverse, "fastq") ):

        fastq_out_F = SeqRecord( F.seq, id = F.id, description = "" )
        fastq_out_F.letter_annotations["phred_quality"] = F.letter_annotations["phred_quality"]

        fastq_out_R = SeqRecord( R.seq, id = R.id, description = "" )
        fastq_out_R.letter_annotations["phred_quality"] = R.letter_annotations["phred_quality"]

        print fastq_out_F.format("fastq"),
        print fastq_out_R.format("fastq"),


if __name__ == '__main__':
    main(sys.argv[1], sys.argv[2])  

5 个答案:

答案 0 :(得分:3)

这可能对您有用:(使用GNU sed)

sed -e 'n;n;n;R file2' -e 'R file2' -e 'R file2' -e 'R file2' file1

或使用paste / bash:

paste -d' ' <(paste -sd'   \n' file1) <(paste -sd'   \n' file2) | tr ' ' '\n'

或:

parallel -N4 --xapply 'printf "%s\n%s\n" {1} {2}'  :::: file1 :::: file2

答案 1 :(得分:1)

可以用纯粹的bash来完成:

f1=""; f2=""
while test -z "$f1" -o -z "$f2"; do
  { read LINE && echo "$LINE" && \
      read LINE && echo "$LINE" && \
      read LINE && echo "$LINE" && \
      read LINE && echo "$LINE"; } || f1=end;
  { read -u 3 LINE && echo "$LINE" && \
      read -u 3 LINE && echo "$LINE" && \
      read -u 3 LINE && echo "$LINE" && \
      read -u 3 LINE && echo "$LINE"; } || f2=end;
done < f1 3< f2

我们的想法是使用一个新的文件描述符(在本例中为3)并同时从stdin读取此文件描述符。

答案 2 :(得分:1)

如果您没有GNU paste,也可以使用sedsed的混合:

paste -d '\n' f1 f2 | sed -e 'x;N;x;N;x;N;x;N;x;N;x;N;x;N;s/^\n//;H;s/.*//;x'

如果您不熟悉sed,则有一个称为保留空间的第二个缓冲区,您可以在其中保存数据。 x命令将当前缓冲区与保留空间交换,N命令将一行附加到当前缓冲区,H命令将当前缓冲区附加到保留空间。

所以第一个x;N在保留空间中保存当前行(因为paste而来自f1)并读取下一行(因为paste而来自f2),然后每个{ {1}}从f1和f2读取一个新行,脚本通过从f2的4行中删除新行完成,将f2中的行放在f1行的末尾,为下一行清除保留空间运行并打印8行。

答案 3 :(得分:0)

您发布的代码看起来非常复杂。编程有一条经验法则:始终有一个更简单的解决方案。在您的情况下,更简单。

您应该做的第一件事是确定输入的限制。你要处理真正的大文件吗?或者他们只有一个或两千字节的大小?这很重要。

第二件事:看看tools you have。使用Python,你有file objects, lists, generators等等。尝试组合这些工具以产生所需的结果。

在您的特定情况下,有一些不明确的要点。如果输入文件的大小不同,脚本应该怎么做?或者其中一个是空的?或者行数不是四分之一?你应该决定如何处理像这样的角落案件。

查看the file objectxrangelist slicinglist comprehensions。如果您更喜欢 cool 方式,您还可以查看itertools模块。

答案 4 :(得分:0)

尝试此操作,更改f1和f2的相应文件名值。

awk 'BEGIN{
  sectionSize=4; maxSectionCnt=sectionSize; maxSectionCnt++
  notEof1=notEof2=1
  f1="file1" ; f2="file2"
   while (notEof1 && notEof2) {
    if (notEof1) {
      for (i=1;i<maxSectionCnt;i++) {
        if (getline < f1 >0 ) { print "F1:" i":" $0 } else {notEof1=0}
      }
    }
    if (notEof2) {
      for (i=1;i<maxSectionCnt;i++) {
        if (getline < f2 >0 ) { print "F2:" i":" $0 } else {notEof2=0}
      }
    }
  }
}'

您还可以删除"F1: i":"等记录标题。我添加了帮助调试代码。

正如Pastafarianist正确指出的那样,如果您对如果文件大小不同等情况会有什么期望等,您可能需要对此进行修改。

我希望这会有所帮助。