将多个文件拆分在一起

时间:2014-05-02 22:10:42

标签: perl bash shell unix awk

我有70个看起来像的文件(file1 = complex.1.txt; ... file69 = complex.69.txt ... file70 = complex.70.txt)

ATOM   7066  O   GLY A 784      49.130  43.743 -23.586  1.00  1.00           O  
nnn
CONECT  337  403 
END
ATOM      1  N   ARG B   1      26.564 -17.621   9.457  1.00  1.00           N1+
ATOM      2  CA  ARG B   1      26.733 -18.764   8.526  1.00  1.00           C  

我想将所有70个文件分成两部分。第二个文件将在END之后开始。对于所有文件,拆分文件名将是complex.1.txt_part1和complex.1.txt_part2,依此类推。 我尝试了awk解决方案

for ((i=1;i<=70;i++)); do awk '{file="complex.1.txt_part"++k;printf "%s%s",$0,RS > file;close(file)}' RS='END\n' complex.$i.txt; done

但它只提供了2个文件。有人可以纠正这个或发布其他好的解决方案。

2 个答案:

答案 0 :(得分:4)

gawk有FILENAME内置变量,可能对您的要求有用。这个单行应该做的工作:

awk 'FNR==1{f=0}{print > FILENAME (f?"_part2":"_part1")}/END/{f=1}' complext.*.txt

答案 1 :(得分:0)

这是一个Perl单线解决方案:

perl -n0e '$k=1; for (split /(?<=^END\n)/m) { open $fh, ">complex.$..txt_part".$k++; print $fh $_ }' complex.*.txt

说明

它使用以下两个特殊的命令行选项:

  
-n
    
...告诉Perl逐个记录读取给定的输入文件,并为每个记录运行指定的一行。默认情况下,记录是一行,但是......
  
-0
    
...告诉Perl处理&#34; null字节&#34;而不是&#34; newline&#34;作为输入记录分隔符,因此整个文件将计为一条记录。


然后在单行代码中:

  • split /(?<=^END\n)/m

    ...将输入记录分成两个字符串,使用look-behind assertion匹配行开头的字符串END,后跟换行符。

  • for (...) { ... }

    ...确保为两个拆分字符串中的每一个单独完成正确的部分

  • open $fh, ">..."; print $fh $_

    ...打开一个新文件进行写入,然后将当前的拆分字符串写入

  • $.

    ...引用当前输入记录编号的特殊变量(即,对于每个读取的记录,它会自动递增1。)

  • $k=1; ... $k++

    ...这样输出文件将以&#34; _part1&#34;结束。在for循环的第一次迭代中,但是&#34; _part2&#34;在第二次迭代中,为每个输入记录。