Программа AWK для определения среднего количества осадков в трех штатах.

Я хочу найти среднее количество осадков в любых трех штатах, скажем, CA, TX и AX за определенный месяц с января по декабрь. Данный входной файл разделен TAB SPACES и имеет формат city name, the state , and then average rainfall amounts from January through December, and then an annual average for all months. ЭГ может выглядеть

AVOCA   PA  30  2.10    2.15    2.55    2.97    3.65    3.98    3.79    3.32     3.31   2.79    3.06    2.51    36.18
BAKERSFIELD CA  30  0.86    1.06    1.04    0.57    0.20    0.10    0.01    0.09    0.17    0.29    0.70    0.63    5.72

Я хочу сделать следующее: «Получить сумму среднего количества осадков, скажем, за определенный месяц февраля, скажем, за n лет, а затем найти его среднее значение для штатов CA, TX и AX.

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

/^CA$/ {CA++; CA_SUM+= $5} # ^CA$ - Regular Expression to match the word CA only 
/^TX$/ {TX++; TX_SUM+= $5} # ^TX$ - Regular Expression to match the word TX only  
/^AX$/ {AX++; AX_SUM+= $5} # ^AX$ - Regular Expression to match the word AX only 
END {
     CA_avg = CA_SUM/CA;
     TX_avg = TX_SUM/TX;
     AX_avg = AX_SUM/AX; 
     printf("CA Rainfall: %5.2f",CA_avg);
     printf("CA Rainfall: %5.2f",TX_avg);
     printf("CA Rainfall: %5.2f",AX_avg);
    }

Я вызываю программу с помощью команды awk 'FS="\t"'-f awk1.awk rainfall.txt и не вижу результата.

Вопрос: Куда я скатываюсь? Любые предложения и измененный код будут оценены


person Eternal Learner    schedule 16.10.2010    source источник
comment
Вы еще не точно описали свои данные; содержание столбца 3 не похоже на количество осадков. Непонятно, как вы относитесь к городу с двумя словами в названии (Маунтин-Вью, Атлантик-Сити).   -  person Jonathan Leffler    schedule 17.10.2010


Ответы (2)


ваше регулярное выражение должно быть

/ CA / {CA++; cA_SUM+= $5} # ^CA$ - Regular Expression to match the word CA only 
/ TX / {TX++; TX_SUM+= $5} # ^TX$ - Regular Expression to match the word TX only  
/ AX / {AX++; AX_SUM+= $5} # ^AX$ - Regular Expression to match the word AX only 

/^AX$/ соответствует, только если это единственное слово в строке

ХТХ!

ИЗМЕНИТЬ

/ CA / {CA++; CA_SUM+= $5} # ^CA$ - Regular Expression to match the word CA only 
/ TX / {TX++; TX_SUM+= $5} # ^TX$ - Regular Expression to match the word TX only  
/ AX / {AX++; AX_SUM+= $5} # ^AX$ - Regular Expression to match the word AX only 
END {

 if(CA!=0){CA_avg = CA_SUM/CA;     printf("CA Rainfall: %5.2f",CA_avg);}
 if(TX!=0){TX_avg = TX_SUM/TX;     printf("TX Rainfall: %5.2f",TX_avg);}
 if(AX!=0){TX_avg = AX_SUM/CA;     printf("AX Rainfall: %5.2f",AX_avg);}
}
person Dr. belisarius    schedule 16.10.2010
comment
@belisarius: я пробовал что-то подобное и получил ошибку деления на ноль BEGIN { FS = \t } ; /\\tCA\\t/ {CA++; cA_SUM+= $5} # ^CA$ - регулярное выражение для соответствия только слову CA /\\tTX\\t/ {TX++; TX_SUM+= $5} # ^TX$ - регулярное выражение для соответствия только слову TX /\\tAX\\t/ {AX++; AX_SUM+= $5} # ^AX$ - регулярное выражение для соответствия только слову AX END { CA_avg = CA_SUM/CA; TX_avg = TX_SUM/TX; AX_avg = AX_СУММ/AX; printf(Дожди в Калифорнии: %5.2f,CA_avg); printf(Дожди в Калифорнии: %5.2f,TX_avg); printf(Дожди в Калифорнии: %5.2f,AX_avg); } - person Eternal Learner; 17.10.2010
comment
@belisarius: Эй, я изменил это на что-то вроде ниже, и это работает s BEGIN {FS = \t}; / КА / {КА++; CA_SUM+= $5} # CA - Регулярное выражение для соответствия слову CA only / TX / {TX++; TX_SUM+= $5} # TX - Регулярное выражение, соответствующее только слову TX / AK / {AK++; AK_SUM+= $5} # AK — регулярное выражение, соответствующее только слову AX END { CA_AVG = CA_SUM/CA; TX_AVG = TX_SUM/TX; АК_АВГ = АК_СУММ/АК; printf(Дожди в Калифорнии: %f,CA_AVG); printf(Дожди в Техасе: %f,TX_AVG); printf(AK Дождь: %f,AK_AVG); } Спасибо за вашу помощь - person Eternal Learner; 17.10.2010

Шаблон /^CA$/ означает, что символы "C" и "A" являются единственными символами в строке. Вы хотите:

$2 == "CA" {CA++; CA_SUM+= $5}
# etc.

Однако это DRYer:

{ count[$2]++; sum[$2] += $5 }
END {
    for (state in count) {
        printf("%s Rainfall: %5.2f\n", state, sum[state]/count[state])
    }
}

Кроме того, это выглядит неправильно: awk 'FS="\t"'-f awk1.awk rainfall.txt
попробуйте: awk -F '\t' -f awk1.awk rainfall.txt


Ответ на комментарии:

awk -F '\t' -v month=2 -v states="CA,AZ,TX" '
    BEGIN {
        month_col = month + 3  # assume January is month 1
        split(states, wanted_states, /,/)
    }
    { count[$2]++; sum[$2] += $month_col }
    END {
        for (state in wanted_states) {
            if (state in count) {
                printf("%s Rainfall: %5.2f\n", state, sum[state]/count[state])
            else
                print state " Rainfall: no data"
        }
    }
' rainfall.txt
person glenn jackman    schedule 16.10.2010
comment
+1 за более общее решение и упоминание DRY в контексте дождя. - person schot; 18.10.2010
comment
+1 Гораздо лучше моего. Я думал только об исправлении ошибок OP, что всегда порождает недальновидный ответ. Вы можете немного улучшить его, разрешив параметр в командной строке для номера месяца. Просто мои 2 цента. - person Dr. belisarius; 21.10.2010
comment
Вы можете изменить версию DRY, чтобы выбрать определенные состояния: awk -v statelist="AK CA TX" 'match(statelist,$2){ count[$2]++; sum[$2] += $5 } .... Или используйте переменную оболочки вместо литерала states="AK CA TX"; awk -v statelist=$states '...' - person Dennis Williamson; 26.10.2010