我有一个大文件。我需要删除文件中第 3 列中数字小于 60 的所有行。
示例文件:
35110 Bacteria(100) Proteobacteria(59) Alphaproteobacteria(59)
12713 Bacteria(100) Bacteroidetes(100) Bacteroidia(100)
期望输出:
12713 Bacteria(100) Bacteroidetes(100) Bacteroidia(100)
答案1
不需要 Gawk 扩展:
awk -F '[()]' '$4 >= 60'
这里awk-F
通过正则表达式集指定的字段标记器[]
:字段由左括号或右括号分隔,因此您会看到第 3 列的数字是第 4 列awk场地。
答案2
您可以使用awk
(实际上它必须是 GNU AWK 实现gawk
,而不是mawk
包含较少功能 - 您可能必须安装它sudo apt install gawk
)来完成这项工作:
gawk '{match($3,/\((.+)\)/,m);if(m[1]>=60){print $0}}' MY_FILE
现在尽管承认这一点看起来就像外行人眼中的黑魔法一样,其逻辑很简单:
- 对于每一行,运行最外层花括号内的内容:
- 首先,
match($3, /\((.+)\)/, m)
将正则表达式\((.+)\)
(匹配开始和结束圆括号,将括号之间的内容存储为第一个捕获组)与$3
已处理输入行的第三列进行匹配,并将生成的匹配数组存储在变量中m
。 - 然后,检查条件
if (m[1] >= 60)
,即匹配的第一个捕获组的值(输入中括号之间的内容)是否大于或等于 60。如果为真,则执行{print $0}
,它只会打印整个当前处理的行。
答案3
这是一个 perl 替代品
perl -alne 'print unless $F[2] =~ /\((\d+)\)$/ && $1 < 60'
- 匹配并捕获第三个(零索引)字段末尾的带括号的十进制数字序列
- 如果找到匹配项,则测试捕获组的数值并进行相应打印
前任。
$ perl -alne 'print unless $F[2] =~ /\((\d+)\)$/ && $1 < 60' file
12713 Bacteria(100) Bacteroidetes(100) Bacteroidia(100)
请注意,这实现了逻辑“删除文件中第 3 列中数字小于 60 的所有行”正如您的问题所述 - 这与打印行数大于或等于 60 略有不同。
如果您的文件确实是用逗号分隔的(而不是问题中所示的空格分隔),那么您将需要更改分隔符,即
perl -F, -lne 'print unless $F[2] =~ /\((\d+)\)$/ && $1 < 60'
答案4
如果您不想学习/使用命令行工具,您不妨在 LibreOffice Calc 中打开文件并过滤数据(Calc 支持制表符分隔的文件)。
如果你知道的话任何编程语言,那么编写一个小程序来过滤数据就很简单了。
但是如果您需要处理大量数据集,使用 MySQL 这样的 DBMS 会更容易、更快捷、更直观。