当此模式在输入文件中多次出现时,如何将特定模式后的一系列行打印到单独的文件中

时间:2015-07-16 06:01:52

标签: python bash awk sed

对不起我以前的帖子,我不知道我在做什么。我试图在给定的输入文件中剪切某些范围的行,并将该范围打印到单独的文件中。此输入文件如下所示:

 18
 generated by VMD
  C         1.514895       -3.887949        2.104134
  C         2.371076       -2.780954        1.718424
  C         3.561071       -3.004933        1.087316
  C         4.080424       -4.331872        1.114878
  C         3.289761       -5.434047        1.607808
  C         2.018473       -5.142150        2.078551
  C         3.997237       -6.725186        1.709355
  C         5.235126       -6.905640        1.295296
  C         5.923666       -5.844841        0.553037
  O         6.955216       -5.826197       -0.042920
  O         5.269004       -4.590026        0.590033
  H         4.054002       -2.184680        0.654838
  H         1.389704       -5.910354        2.488783
  H         5.814723       -7.796634        1.451618
  O         1.825325       -1.537706        1.986256
  H         2.319215       -0.796042        1.550394
  H         3.390707       -7.564847        2.136680
  H         0.535358       -3.663175        2.483943
 18
  generated by VMD
  C         1.519866       -3.892621        2.109595

我想从第一帧开始每隔100帧打印一个名为"snapshot0.xyz"的文件(第一帧是第0帧)。

例如,上面的输入显示了两个快照。我想将行1:20打印到自己的名为snapshot0.xyz的文件中,然后跳过100(2000行)快照并打印出snapshot1.xyz (with the 100th snapshot)。我的尝试是在python中,但您可以选择grepawksedPython

我的输入文件:frames.dat

  1 #!/usr/bin/Python
  2 
  3 
  4 
  5 mest = open('frames.dat', 'r')
  6 test = mest.read().strip().split('\n')
  7 
  8 for i in range(len(test)):
  9         if test[i] == '18':
 10                 f = open("out"+`i`+".dat", "w")
 11                 for j in range(19):
 12                         print >> f, test[j]
 13         f.close()

2 个答案:

答案 0 :(得分:0)

我建议使用csv模块进行此输入。

import csv

def strip_empty_columns(line):
    return filter(lambda s: s.strip() != "", line)

def is_count(line):
    return len(line) == 1 and line[0].strip().isdigit()

def is_float(s):
    try:
        float(s.strip())
        return True
    except ValueError:
        return False

def is_data_line(line):
    return len(line) == 4 and is_float(line[1]) and is_float(line[2]) and is_float(line[3])

with open('frames.dat', 'r') as mest:
    r = csv.reader(mest, delimiter=' ')
    current_count = 0
    frame_nr = 0
    outfile = None

    for line in r:
        line = strip_empty_columns(line)
        if is_count(line):
            if frame_nr % 100 == 0:
                outfile = open("snapshot%d.xyz" % frame_nr, "w+")
            elif outfile:
                outfile.close()
                outfile = None
            frame_nr += 1 # increment the frame counter every time you see this header line like '18'
        elif is_data_line(line):
            if outfile:
                outfile.write("    ".join(line) + "\n")

开场文章提到将每100帧写入名为snapshot0.xyz的输出文件。我假设0应该是一个计数器,你会不断覆盖该文件。我使用frame_nr计数器更新了代码,并根据frame_nr打开/关闭输出文件,并在输出文件打开时写入数据。

答案 1 :(得分:0)

这可能适合你(GNU sed和csplit):

sed -rn '/^18/{x;/x{100}/z;s/^/x/;x};G;/\nx$/P' file | csplit -f snapshot -b '%d.xyz' -z - '/^18/' '{*}'

使用sed过滤每100帧,并将该文件传递给csplit以创建单个文件。