Сумма в блоке с AWK (перезапускают сумму, когда шаблон изменяется),

Проблема с Вашим $PATH переменная среды. Вы, скорее всего, испортили его. Это должно быть подобно этому:

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Посмотрите этот поток Linux Mint: http://forums.linuxmint.com/viewtopic.php?f=18&t=119561.

Можно восстановить Ваш $PATH в оболочке с этой командой:

$ export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

Это является временным! Если проблема сохраняется с перезагрузкой затем, Вы, скорее всего, полили из шланга $PATH в одном из Ваших файлов установки среды под /etc.

5
08.07.2014, 12:12
2 ответа
[

]Я не совсем уверен, что ваш []если[] пытается сделать там. []NR[] - это количество записей; используйте []NF[] для количества полей, если это то, к чему вы стремитесь. Нельзя ставить блоки []{}[] посередине таких вещей.[

] [

] Я думаю, что вы стремитесь сравнить значение поля в этой строке с полем в предыдущей строке, распечатывая сумму, когда мы достигнем новой "группы" данных. Если это так, то этот скрипт будет делать то, что вы хотите, и я думаю, что это приравнивается практически к тому, к чему вы стремились:[

] [
{
    if (last && $1 != last) {
        print last, sum
        sum = 0
    }
    sum = sum + $2
    last = $1
}
END {
    print last, sum
}
] [

]Мы делаем новую переменную []последнюю [], чтобы удержать значение первого поля ([]$1[]) в предыдущей строке. Мы будем использовать это для отслеживания, на какую группу мы смотрим.[

] [
    ] [
  • ]Для каждой строки (так как на верхнем уровне у нас []{ ... }[]), мы сначала проверяем, установлено ли a) []last[] (так как мы не хотим выводить ничего в самой первой строке), и b) значение первого поля отличается от значения []last[]. Если это так, то мы выведем значение []last[], пробел (из-за [], []), и вычисленную нами сумму []sum[]. (Если вам нужна вкладка, используйте [] "\t"[] в кавычках, как у вас было)[
  • ] [
  • ] После распечатки мы обнуляем []sum[].[
  • ] [
  • ] В любом случае, мы добавляем значение второго поля ([]$2[]) к []sum[]. [
  • ] [
  • ]Для каждой строки мы сохраняем первое поле (наша группа) в []последнее[], поэтому можем использовать его для сравнения в следующей строке.[
  • ] [
  • ]Наконец, мы хотим вывести и последнюю группу. Для этого мы используем []END { ...]. }[] блок. Он запускается прямо в конце программы, когда у нас заканчиваются данные. Мы распечатываем сумму и группу, с которой работаем, так же, как и раньше.[
  • ] [
] [

]Если я запущу:[

] [
awk -f sum.awk < data
] [

]с вашим файлом данных, то получу этот вывод:[

] [
A 600
B 900
A 2100
] [

]как надо.[

] [
] [

]Есть более простые способы сделать это, как в awk, так и в других местах. В частности, мы можем заменить тело, приведенное выше, на:[

] [
last && $1 != last {
    print last, sum
    sum = 0
}
{
    sum = sum + $2
    last = $1
}
] [

]Здесь мы используем условный синтаксис блока awk, а не явный []if[] тест: поведение этой программы идентично приведенному выше, но более идиоматично. В этом примере он не сильно отличается, но полезно знать о том, изучаете ли вы awk.[

] [
] [

] Если приведенный вами пример файла является буквально тем, что он есть, со строками []#sum=[] (или аналогичными), вы можете использовать этот сценарий:[

] [
{
    sum = sum + $2
    if (NF == 3) {
        print $1, sum
        sum = 0
    }
}
] [

]Для каждой строки, это добавляет значение второго поля к переменной []sum[]. На строках, которые имеют ровно три поля ([]NF == 3[]), мы распечатываем нашу сумму, и сбрасываем []sum[] на ноль.[

].
6
27.01.2020, 20:36
[

] Если ваш файл достаточно мал для того, чтобы все суммы поместились в память, вы можете сделать что-то настолько простое, насколько это возможно: [

] [
$ awk '{sum[$1]+=$2}END{for(pat in sum){print pat,sum[pat]}}' file 
A 2700
B 900
] [

] Вот то же самое, что и закомментированный скрипт []awk[]:[

] [
#!/usr/bin/awk -f

{
    ## Here, we use $1 as the key of an associative array
    ## and increment its current value by $2. The result of 
    ## this will be an array element for each different $1 in 
    ## the file whose value will be the sum of all associated $2s.
    sum[$1]+=$2
}

## The END{} block is exacuted after the entire file
## has been processed.
END{
    ## Iterate through the keys of the array (the $1s),
    ## saving each as 'pat'. Then, print the current value of
    ## 'pat' as well as the associated value (the sum) from
    ## the array.
    for(pat in sum){
        print pat,sum[pat]
    }
}
] [

] Единственная возможная проблема с этим подходом - если у вас так много строк, что сохранение массива []$1[]s приведет к тому, что у вас закончится память. В современной системе это маловероятно. С другой стороны, этот подход также работает, когда строки Вашего файла не в порядке, так как он может работать с несортированными файлами.[

].
2
27.01.2020, 20:36

Теги

Похожие вопросы