У меня есть большой файл. Я должен удалить все строки в файле, которые имеют число меньше чем 60 в столбце 3.
Файл в качестве примера:
35110 Bacteria(100) Proteobacteria(59) Alphaproteobacteria(59)
12713 Bacteria(100) Bacteroidetes(100) Bacteroidia(100)
Желаемый вывод:
12713 Bacteria(100) Bacteroidetes(100) Bacteroidia(100)
Никакая потребность в расширениях Простофили:
awk -F '[()]' '$4 >= 60'
Здесь awk полевой токенизатор, указанный через -F
набор regex []
: поля разделяются или открытием или закрывающей скобкой, следовательно Вы видите, что число Вашего 3-го столбца является 4-м awk полем.
Можно использовать awk
(на самом деле это должна быть реализация AWK GNU 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}
, который просто печатает целую в настоящее время обрабатываемую строку.Вот альтернатива жемчуга
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)
Обратите внимание, что это реализует логику, "удаляют все строки в файле, которые имеют число меньше чем 60 в столбце 3", как указано в Вашем вопросе - который немного отличается от печати строк, которые имеют число, больше, чем или равный 60.
Если Ваши файлы действительно будут разделенной запятой (а не пробел, разграниченный как показано в Вашем вопросе), то необходимо будет изменить разделитель т.е.
perl -F, -lne 'print unless $F[2] =~ /\((\d+)\)$/ && $1 < 60'
Если Вы не хотите изучать/использовать инструменты командной строки, Вы могли бы также открыть файл в LibreOffice Calc и просто отфильтровать данные (Calc поддерживает разделенные от вкладки файлы).
Если Вы знаете какой-либо язык программирования, то это тривиально для записи небольшой программы для фильтрации данных.
Но если бы у Вас есть большой набор данных для обработки, использование DBMS как MySQL было бы легче, быстрее и интуитивным.