根据其他列的值过滤列

根据其他列的值过滤列

我有一个包含两列和超过 3,00,000 行的文本文件。格式如下

Filename1.txt Num1
Filename2.txt Num2
Filename3.txt Num3

我想将对应Numx大于 50 且小于 200 的所有文件名复制到另一个文件中。

将这些文件名复制到另一个文件后,我想将所有这些文件复制到另一个文件夹中。

我怎么做?

答案1

如果您愿意,可以同时进行比较和复制awk

awk '$2>50 && $2<200 {system("cp -- "$1" /path/to/destination/")}' file.txt

假设您要将文件复制到destination目录,请更改此值以满足您的需要。

  • $2>50 && $2<200进行所需的比较

  • 如果匹配,则cp执行操作 ( {system("cp -- "$1" /path/to/destination/")}),由system()函数完成awk

答案2

让我们考虑这个测试文件:

$ cat file
Filename1.txt 49
Filename2.txt 72
Filename3.txt 189
Filename4.txt 203

仅选择第二列大于或等于 50 且小于或等于 200 的文件:

$ awk '$2>=50 && $2<=200 { print $1}' file
Filename2.txt
Filename3.txt

要将这些文件名放入某个路径的新文件中:

awk '$2>=50 && $2<=200 { print $1}' file >/path/to/newfile

复制选定的文件

假设数字是整数,请尝试:

while read fname num; do [ "$num" -ge 50 ] && [ "$num" -le 200 ] && cp -- "$fname" /some/path/ ; done <file

或者,对于那些喜欢将代码分散在多行中的人:

while read fname num
do
   [ "$num" -ge 50 ] && [ "$num" -le 200 ] && cp -- "$fname" /some/path/
done <file

答案3

问题已标记,所以我假设有人对使用正则表达式的答案感兴趣。另外,问题表明输入数据文件很大,因此我认为性能是一个考虑因素。

我还假设,鉴于输入文件每行包含一个文件名,因此不会有包含换行符的(病态)文件名。

其他答案有效地cp为每个文件生成一个进程。这会导致不必要的性能降低。相反,我们可以使用命令行xargs来调用cp尽可能多的文件名。

sed -rn 's/ (5[1-9]|[6-9].|1..)$//p' input.txt | tr '\n' '\0' | xargs -0 cp -t /destdir

使用sed正则表达式来匹配闭合数值区间(50, 200)。使用正则表达式来解决数值不等式并不总是最优雅的事情,但在这种情况下,所需的表达式相当简单。

我们假设文件名不包含换行符,但它们可能包含其他无用的字符,例如空格。 xargs如果给定分隔数据,将正确处理此问题\0,因此我们使用tr将所有换行符转换为空字符。

上面假设sed和是 GNU 版本xargs。如果您有 BSD 版本(例如 OSX),则命令略有不同:

sed -En 's/ (5[1-9]|[6-9].|1..)$//p' input.txt | tr '\n' '\0' | xargs -0 -J {} cp {} /destdir

这些命令将生成sedtr和的一份副本xargs。将会有多个 的生成cp,但每个生成都会复制多个文件 -xargs将尝试填充每个cp命令行以实现高效利用。当输入数据很大时,这应该比其他答案提供显着的性能改进。

相关内容