【问题标题】:Find pattern in file and print every xth occurrence to another file [closed]在文件中查找模式并将每第 x 次出现打印到另一个文件 [关闭]
【发布时间】:2021-12-22 09:25:08
【问题描述】:

我有一个非常大的文件,类似于下面的 sn-p。 sn-p 显示三个数据块。它们来自三个不同的时间步长 (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 在下面链接中的答案看起来很有希望(如果我理解,其他答案取决于数据块之间的空白行,而我没有)。我已经设法使用它将每个不同的块打印到自己的文件中。但我最终得到了太多文件。如果有人知道如何调整 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我需要将这一行和每 xth 行打印到一个新文件中,这样我就有了两个文件,其中包含来自相同时间步长的数据。

我可以想办法将每第 x 行放入一个新文件中,但如果有办法确保前两列与上面 (1) 中的 i = 0, time = 0.000 匹配,那就太好了(所以我不知道'如果一行未能打印或文件中重复了一个时间步,则不会以不匹配结束)。

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

【问题讨论】:

  • 这似乎(对我来说)是 2 个不同的问题;我建议将第二个问题分成第二个/单独的问题,或者......从这个问题中删除第二部分,等待看看你得到什么答案,看看你是否可以修改所说的答案以适合你的第二个问题和 然后如果您遇到问题,请创建第二个问题...... ???
  • 对于第 1 期,请更新问题,详细说明如何确定新文件名
  • 不要显示 3 个块并说您希望每 100 个块写入一个新文件,因为您无法显示,我们也无法对其进行测试。而是创建一个minimal reproducible example,例如,7 个 shorter 块(例如,每个块 3 行而不是 8 行),告诉我们您希望每 3 个块写入一个新文件而不是每 100 个块,然后包括预期的输出文件。这将阐明您的要求并为我们提供一些我们可以复制/粘贴进行测试的内容,您可以稍后在必要时调整答案,例如将 3 更改为 100。
  • 那么您是否只想将每 100 个块的 itime 打印到一个新的(空)文件中?以及,每 100 块完整打印一次,分别?对于每 100 个完整的块,我有一个简单的 awk 解决方案,但我不确定您在另一个文件中究竟需要什么。只有两列?
  • @markp-fuso,抱歉延迟响应(停电)。谢谢您的帮助。新文件名可以是相应的时间步长。即“0, 1, 2, ...”但是,我看到您已经留下了答案,所以我会先介绍一下,然后再在这里进一步回复,可能会让大家感到困惑。

标签: file awk sed file-io


【解决方案1】:

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

假设:

  • 每个块由 8 行组成(独立的6i = ... 行和 6 个数据行)
  • 每个感兴趣的 8 行块被转储到单独的输出文件中
  • 输出文件名格式:block.&lt;block_count&gt;.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}" '
$1 == "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

【讨论】:

  • 我得到: awk -vx='${x}' ' (^ 语法错误)和 awk -vx='${x}' ' (^ invalid char ''' in expression )。我现在正在寻找解决方案,似乎它可能是 Linux 与 Windows 的事情。不要觉得你必须解决它,但我只是想我会提到它,以防你见过它。谢谢。
  • 您是直接从我的回答中剪切粘贴,还是手动将代码输入到脚本中?另外,当你运行awk --version 时你会得到什么?如果你不能让它工作,我建议你用你正在运行的代码的精确副本、错误消息和awk --version 的输出来更新问题(最后)
  • 我一开始是剪切粘贴的!然后我手动输入所有内容并得到相同的错误。我的 awk 版本是 4.0.2(在外部机器上)。
  • 您确定为 OS/bash 变量 x 设置了一个值吗? (示例中的x=2 - 以上)
  • 非常感谢@markpfuso。我让它工作了。不幸的是,有人已经结束了这个问题,但我希望你仍然会得到信任。
【解决方案2】:

这可能对你有用(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 行,然后交换到保持空间,递增计数器,测试计数器是否出现所需的次数(在本例中为 100),如果是,则将计数器归零,交换回模式空间,打印它,然后返回到保持空间。在所有情况下都返回到模式空间。

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

【讨论】:

  • 非常感谢。我不能让它工作,但会继续努力。毫无疑问,我在某个地方犯了一个愚蠢的错误。我很感激你的时间。我正在练习我的 sed 和 Awk,但这是一个缓慢的过程!
  • 谢谢你,@potang。我发现了我的问题并让它工作了。
猜你喜欢
  • 1970-01-01
  • 2017-02-15
  • 2015-12-25
  • 1970-01-01
  • 2014-03-09
  • 1970-01-01
  • 2020-01-17
  • 2016-01-28
  • 1970-01-01
相关资源
最近更新 更多