文本操作:从排序列表中删除值 x

文本操作:从排序列表中删除值 x

我的输入文本文件包含一个 1 行标题,然后是一个排序的行列表,其中包含: xy 和 x,y 64 位整数,以空格分隔。输入文件长达数百万行。

现在我想要从第 2 行删除到#end#任何以值 <= $input 开头的行。这会删除每场比赛的完整行。到目前为止,我的不优雅的解决方案是:

head -1 inputFile > inputFile2 # 保留标头
lineNum=$( grep -n $input test | cut -f1 -d ':' ) # 查找与 $input 匹配的行
tail -n +$( $lineNum+1 ) inputFile >> inputFile2 # 向下跳过输入,直到到达 value > $input
rm 输入文件
mv 输入文件2 输入文件

输入文件示例

5066314878607:a1:a2:a3:a4:a5
1 27
3 27
7 27
11 27
13 27
17 27
...

[GNU Tool split] inputFile 分为 inputFile-1 和 inputFile-2(2 个核心,可能是 z 核心)

输入文件-1:
5066314878607:a1:a2:a3:a4:a5
1 27
7 27
13 27

输入文件-2
5066314878607:a1:a2:a3:a4:a5
3 27
11 27
17 27

现在 inputFile-1 已处理并完成了直到 '727'。从主 inputFile 中,我只想包含以下两行:(注意 <= 在分割 inputFile-1 中,但这不是简单的 <= x 由于循环分割而从原始 inputFile 中删除)

1 27
7 27

这使得 inputFile 为:

5066314878607:a1:a2:a3:a4:a5
3 27
11 27
13 27
17 27

在当前的 Ubuntu 16.04 上运行,尽管对于任何现代 Linux 发行版来说这可能都是相同的。

问题:

  • 我现有的代码可以改进吗?
  • 我如何概括它来处理许多单独的删除文件?

每个单独处理的 inputFile-x 将按顺序处理。我只是不知道如何处理通过循环拆分从主文件中删除已处理的行。 特别是,由于它在许多不同速度的计算机上运行,​​因此 inputFile-1 可能会被处理到第 300 行,而 inputFile-2 可能会被处理到第 500 行。

解释如何推广到 z 核,每个核分别进行处理。 inputFile 是循环分割成 inputFile-1 inputFile-2 inputFile-3 ... inputFile-z [即 split -nr/$z,对于 50 个核心: split -nr/50 inputFile ]

Core1:inputFile-1(第2行到#end#的值)<= $input1 --> 存储列表/数组remove1。现在,仅从原始 inputFile 中删除remove1 中的匹配值。继续处理每个核心。

答案1

@SatoKatsura 已经在评论中回答了你的第一个问题:awk -v cutoff=299851915672 'FNR == 1 || $1+0 > cutoff+0' inputFile

很难解释您在第二个问题中提出的问题(您可以用算法或伪代码更新您的问题吗?),但听起来您想要在以下位置运行流程的许多(50?)实例一次(系统上每个 CPU 核心一次)。如果是这样,则您已正确开始将文件拆分为 50 个较小的文件。

难题中缺少的一部分是您需要使用 GNU parallel(或者,xargs使用-P选项)来并行运行进程。例如:

find . -type f -name 'inputFile-*' -print0 |
    parallel -n 1 \
    awk -v cutoff=299851915672 \
      \'FNR == 1 \|\| \$1+0 > cutoff+0 {print \> FILENAME".out"}\'

(参见下面的注释 1、2 和 3)

parallel默认情况下,系统上每个核心运行一个进程。您可以通过使用-j指定同时作业数量的选项来覆盖它。

awk脚本将每个输入文件的输出保存为一个具有相同名称和额外.out扩展名的文件 - 例如inputFile-1-> inputFile-1.out。要将它们再次合并到一个大文件中,您可以使用cat

cat inputFile*.out > complete.output.txt
rm -f *.out

注意1:您需要在要执行的命令行上使用反斜杠转义引号和其他特殊字符(例如,,,,,|等等)。将脚本保存在独立文件中(使用作为第一行),使用 使其可执行,并并行运行该脚本会更容易。$>&;parallelawk#!/usr/bin/awk -fchmod

注意2:这可能不会完全满足您的要求,因为我不知道您实际要求的是什么。它是如何并行处理多个文件的一般示例。awk几乎肯定需要更改脚本才能满足您(难以理解的)要求。

注意3:您可能会发现并行运行多个进程所节省的时间远远超过将输入拆分为多个文件所需的时间以及awk为每个文件启动新进程实例(例如脚本)的开销。文件。这取决于文件的性质和大小,以及要对每个文件执行的处理的性质。并行运行并不总是意味着更快地获得结果。或者您正在做的事情可能过于复杂,因此很难理解和/或用其他数据复制。

答案2

我们可以避免读取整个文件吗?是的:因为它是排序的,所以我们可以进行二分查找来找到相关行的字节: 在已排序的文本文件中进行二分查找https://gitlab.com/ole.tange/tangetools/blob/master/bsearch/bsearch

我们可以避免处理大多数行吗?是的,一旦我们找到了相关行,我们就可以复制其余的内容。

使用该字节,您可以执行head1 行标题的操作,并tail从找到的字节执行操作。

相关内容