Скрипт AWK, который подсчитывает количество экземпляров для каждого раздела - PullRequest
0 голосов
/ 27 августа 2018

Возможно, AWK не лучший язык кодирования для задачи, на которой я пытаюсь его использовать.Я знаком с Python, но мне просто нравится использовать AWK в подобных случаях.Вот моя проблема с кодированием.У меня есть файл, который выглядит следующим образом:

name1 0
name1 1
name1 0
name1 1
name2 0
name2 0
name3 1
name3 1
name3 1
name3 0

Я пытаюсь подсчитать количество 0 и 1 для каждого из разных имен (они доходят до 3000). Так, например, яЯ хотел бы напечатать следующее в новом файле

name1 2 2    #There are 2 ones and 2 zeros
name2 0 2    #There are 0 ones, and 2 zeros
name3 1 3    #There are 1 one, and 3 zeros

Подсчет 0 и 1 очевиден, и я бы использовал простое выражение if / else

awk '{
if (variable == false)
    while (
if ($2 == 0)
    a++;
else
    b++;
}' 

Как бы ячтобы убедиться, что я рассчитываю на каждое из имен?

Ответы [ 3 ]

0 голосов
/ 27 августа 2018

Если ваш вход отсортирован, как в вашем примере, то с любым awk:

$ awk '
    NR>1 && $1!=prev { print prev, cnt[1]+0, cnt[0]+0; delete cnt }
    { cnt[$2]++; prev=$1 }
    END { print prev, cnt[1]+0, cnt[0]+0 }
' file
name1 2 2
name2 0 2
name3 3 1

в противном случае, если вход не отсортирован, тогда с GNU awk для истинных многомерных массивов:

$ awk '
    { cnt[$1][$2]++ }
    END{ for (key in cnt) print key, cnt[key][1]+0, cnt[key][0]+0 }
' file
name1 2 2
name2 0 2
name3 3 1

или с любым awk:

$ awk '
    { cnt[$1,$2]++; keys[$1] }
    END { for (key in keys) print key, cnt[key,1]+0, cnt[key,0]+0 }
' file
name1 2 2
name2 0 2
name3 3 1
0 голосов
/ 27 августа 2018

Есть простой способ сделать это, просто используя параллельные ассоциативные массивы следующим образом:

    $2 == 0 { zero[$1] += 1; one[$1] += 0 }
    $2 == 1 { zero[$1] += 0; one[$1] += 1 }
    END { for (key in zero) { print key" "one[key]" "zero[key] } }

Это игнорирует все строки, которые не имеют ноль или одну в качестве второйи корректно обновляет параллельные массивы (т. е. добавляет соответствующее значение к обоим массивам), чтобы упростить постобработку.

Постобработка просто включает в себя перебор ключей one массивов и распечатки значений из обоих.Правильное обновление, упомянутое в предыдущем абзаце, гарантирует, что каждый ключ будет в обоих массивах.

0 голосов
/ 27 августа 2018

Вы должны попробовать с awk массивами:

awk '{
m[$1,$2]++;a[$1]
}
END{
for(i in a) 
   print i, (m[i,"1"] ? m[i,"1"] : "0") , (m[i,"0"] ? m[i,"0"] : 0) 
}'  names
  • Первый массив m используется, чтобы сохранить поле + число и использовать его позже.
  • Второйis array a - запомнить первое поле.
  • (m[i"1"] ? m[i"1"] : "0") , (m[i"0"] ? m[i"0"] : 0) - троичный оператор, используемый в случае отсутствия чего-либо в m.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...