在文件中查找模式并将每第 n 次出现打印到另一个文件

Find pattern in file and print every xth occurrence to another file

我有一个非常大的文件,类似于下面的代码片段。该片段显示了三个数据块。它们来自三个不同的时间步长 (i)。

6 # <--This is the same for all data blocks (i.e., always 6 rows of data)
i =        0, time =        0.000, k =      9000000000000
X        -7.6415350292        6.0494971539        8.1919697993
Y        -6.6418362233        5.9231018862        8.4056822626
Y        -8.0518670684        6.3158684817        9.0061271154
X        26.8252967820       20.4661074967       17.8025744066
Y        26.4477411207       20.4071029058       16.9121571912
Y        26.4399648474       21.2950722068       18.1009273227
6
i =        1, time =        0.500, k =      2500000000000
X        -6.2423192714       -1.5704681396       -9.5648670474
Y        -5.4925100813       -1.6522059045       -8.9030589772
Y        -6.7765278574       -2.3616512405       -9.4776648590
X         4.1248924594       27.8487302083      -17.5400886312
Y         4.1238657681       26.9869907778      -17.9727402579
Y         5.0750649402       28.1292768156      -17.6848507559
6
i =        2, time =        1.000, k =      3945000000000
X        19.0090162215       -5.9338939011        6.1931167954
Y        18.4748060757       -6.4905073540        5.6656446036
Y        19.2825591449       -6.4479943255        7.0179774953
X        11.0203415273       34.6029396705        2.7220660957
Y        11.1184002007       34.8398120338        1.8089008500
Y        10.3349649622       33.9509485292        2.5605794622
  1. 我想每第 100 个数据块打印到一个新文件。

@potong 在下面 link 的回答看起来很有希望(如果我理解,其他答案取决于数据块之间的空白行,而我没有)。我设法用它来将每个不同的块打印到它自己的文件中。但是我最终得到了太多文件。如果有人知道如何调整 potong 的方法以便它只适用于每个 xth 块,我将非常感谢您的提示。

Find specific pattern and print complete text block using awk or sed

  1. 如果我这样做,我需要对第二个(对应的)文件进行类似的修改,如下所示:

    0       0.000       13.6600000000        0.0000000000        0.0000000000        0.0000000000       13.6600000000        0.0000000000        0.0000000000        0.0000000000       13.6600000000          2548
    

这是第一行。前两列对应上面第一个数据块中的i = 0, time = 0.000我需要将这一行和每第 x 行打印到一个新文件,这样我就有两个包含来自相同时间步的数据的文件。

我可以想办法将每 xth 行放入一个新文件中,但如果有办法确保前两列与上面 (1) 中的 i = 0, time = 0.000 匹配,那将是很好的了解 (这样,如果一行打印失败或文件中重复了一个时间步长,我就不会以不匹配结束。

我添加了一个“Awk”标签,因为这似乎是 Awk 可以做的事情,但我没有使用 Awk 的经验。

注意: 仅解决 OP 的第一个要求,即每第 100 个块打印到 separate/new 文件 ...

假设:

  • 每个块由 8 行组成(独立 6i = ... 行和 6 条数据行)
  • 将每个感兴趣的 8 行块转储到单独的输出文件
  • 输出文件名格式:block.<block_count>.dat(OP 可以根据要求更改)

示例数据:

$ cat  block.dat
6 # block #1
i =        0, time =        0.000, k =      9000000000000
X        -7.6415350292        6.0494971539        8.1919697993
Y        -6.6418362233        5.9231018862        8.4056822626
Y        -8.0518670684        6.3158684817        9.0061271154
X        26.8252967820       20.4661074967       17.8025744066
Y        26.4477411207       20.4071029058       16.9121571912
Y        26.4399648474       21.2950722068       18.1009273227
6 # block #2
i =        1, time =        0.500, k =      2500000000000
X        -6.2423192714       -1.5704681396       -9.5648670474
Y        -5.4925100813       -1.6522059045       -8.9030589772
Y        -6.7765278574       -2.3616512405       -9.4776648590
X         4.1248924594       27.8487302083      -17.5400886312
Y         4.1238657681       26.9869907778      -17.9727402579
Y         5.0750649402       28.1292768156      -17.6848507559
6 # block #3
i =        2, time =        1.000, k =      3945000000000
X        19.0090162215       -5.9338939011        6.1931167954
Y        18.4748060757       -6.4905073540        5.6656446036
Y        19.2825591449       -6.4479943255        7.0179774953
X        11.0203415273       34.6029396705        2.7220660957
Y        11.1184002007       34.8398120338        1.8089008500
Y        10.3349649622       33.9509485292        2.5605794622
6 # block #4
i =        2, time =        1.000, k =      3945000000000
X        19.0090162215       -5.9338939011        6.1931167954
Y        18.4748060757       -6.4905073540        5.6656446036
Y        19.2825591449       -6.4479943255        7.0179774953
X        11.0203415273       34.6029396705        2.7220660957
Y        11.1184002007       34.8398120338        1.8089008500
Y        10.3349649622       33.9509485292        2.5605794622

一个 awk 想法打印出每个 xth 区块

x=2                         # set to 100 per OP's requirement

awk -v x="${x}" '
 == "6"    { count++ }
!(count % x) { print > "block." count ".dat"}
' block.dat

这会生成:

for f in block.*.dat
do
    echo "########### $f"
    cat $f
done

########### block.2.dat
6 # block #2
i =        1, time =        0.500, k =      2500000000000
X        -6.2423192714       -1.5704681396       -9.5648670474
Y        -5.4925100813       -1.6522059045       -8.9030589772
Y        -6.7765278574       -2.3616512405       -9.4776648590
X         4.1248924594       27.8487302083      -17.5400886312
Y         4.1238657681       26.9869907778      -17.9727402579
Y         5.0750649402       28.1292768156      -17.6848507559
########### block.4.dat
6 # block #4
i =        2, time =        1.000, k =      3945000000000
X        19.0090162215       -5.9338939011        6.1931167954
Y        18.4748060757       -6.4905073540        5.6656446036
Y        19.2825591449       -6.4479943255        7.0179774953
X        11.0203415273       34.6029396705        2.7220660957
Y        11.1184002007       34.8398120338        1.8089008500
Y        10.3349649622       33.9509485292        2.5605794622

这可能适合您 (GNU sed):

sed -nE '/^6/{:a;N;s/[^\n]*/&/8;Ta;x;s/^/x/;/x{100}/{z;x;p;x};x}' file

关闭隐式打印并启用扩展正则表达式 -nE

从以 6 开头的行开始,收集 8 行然后交换到保持 space,递增计数器,测试计数器是否出现所需的次数(在本例中为 100 ) 如果是,则将计数器归零,换回模式 space,打印它,然后 return 到保留 space。在所有情况下 return 到模式 space.

N.B。可以更改记录中的行数(在本例中为 8)以及输出记录数(在本例中为 100)。