Удалить строку, содержащую 0 более 'x' раз.

Удалить строку, содержащую 0 более 'x' раз.

У меня большой файл с разделителями-запятыми. Мне нужно отфильтровать строки, содержащие x столбцов с нулями (исключая первую строку). Для простоты предположим, что я хочу отфильтровать строки с более чем 4 нулями:

    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2
    gene3,0,0,0,0,6,0,0

Вернулись бы:

    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2

Отфильтровываем «gene3».

Вот что я попробовал (попытка использовать «,0» в качестве разделителя, но безуспешно):

awk -F',0' 'NF<4 {print}' file.csv

решение1

При этом awk -F',0'три копии ,0будут считаться тремясепараторы, давая четыреполяв общей сложности. Так что если вы используете awk -F',0' 'NF<5 {print}'вместо этого, вы должны увидеть правильные строки в выводе.

,0также будет соответствовать строкам типа 213,0123, которые вы можете использовать или не использовать в качестве разделителей нулей.

Таким образом, вы также можете использовать ,в качестве разделителя полей и подсчитать поля, в которых есть только один ноль:

awk -F, '{z=0; for (i = 1 ; i <= NF ; i++) if ($i == 0) z++} z <= 4' file.csv

решение2

Вы также можете решить свою проблему, используя регулярные выражения и grep.

grep -Ev '(,0(,[^0,]+)*){4,}' file.csv

Я проверил это на этом файле:

gene,v1,v2,v3,v4,v5,v6,v7
gene1,0,1,5,0,0,4,100
gene2,1,0,0,0,5,210,2
gene3,0,0,0,0,6,0,0
gene4,0,0,0,4,6,0,0
gene5,0,1,0,4,6,0,0

Есть некоторые предположения:

  • ни одно ненулевое число не начинается с нуля,
  • нулевые числа содержат только один ноль,
  • все числа являются целыми.

Регулярное выражение можно расширить для решения таких задач, если это необходимо.

решение3

Подход KISS, сawk

awk -F, '{c = 0; for(i=1; i<=NF; i++) {c += $i == "0" ? 1 : 0}} c <= 3' file.csv
    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2

Сperl

perl -F, -ne 'print unless (grep { $_ eq "0" } @F) > 3' file.csv
    gene,v1,v2,v3,v4,v5,v6,v7
    gene1,0,1,5,0,0,4,100
    gene2,1,0,0,0,5,210,2

решение4

Если все числа целые, то с помощьюГНУ awkкоторый поддерживает границы слов \<...\>, вы могли бы сделать

gawk 'gsub(/\<0\>/, "0") <5' infile

Связанный контент