2015-07-04 2 views
1

Я пытаюсь умножить поле $ 2 либо .75 или .1AWK шаблону с, если

У меня есть эти данные:

Disputed,279 
Processed,12112 
Uncollected NSF,4732 
Declined,14 
Invalid/Closed Account,3022 

Awk заявление:

#!/usr/local/bin/gawk -f 

BEGIN { FPAT="([^,]*)|(\"[^\"]+\")"; FS=OFS=","; OFMT="%.2f"; } 

{ 
     if ($1 "/Disputed|Uncollected|Invalid/") 
       $3 = $2 * .75 
     else 
       if ($1 ~ "/Processed|Declined/") 
       $3 = $2 * 0.10 
     print 
} 

Прогнозный выход:

Disputed,279,209.25 
Processed,12112,1211.2 
Uncollected NSF,4732,3549 
Declined,14,1.4 
Invalid/Closed Account,3022,2266.5 

Актуальная резина ULTS:

Disputed,279,209.25 
Processed,12112,9084 
Uncollected NSF,4732,3549 
Declined,14,10.5 
Invalid/Closed Account,3022,2266.5 

Они умножаются на .75: Спорный, Несобранный НФС и Invalid/Closed счет

Они умножаются на .1: Переработанные и Отклонены

, что вызывает все записи должны быть умножены .75?

редактировать: это мой рабочий раствор ...

#!/usr/local/bin/gawk -f 

BEGIN { 
    FPAT="([^,]*)|(\"[^\"]+\")" 
    FS=OFS="," 
    OFMT="%.2f" 
    print "status","acct type","count","amount" 
} 

NF>1 { 
    $4=$3 * ($1 ~ /Processed|Declined/ ? 0.10 : 0.75) 
    print 
    trans+=$3 
    fee+=$4 
} 

END { 
    printf "------------\n" 
    print "# of transactions: " trans 
    print "processing fee: " fee 
} 

Да, есть четыре поля. $ 2 - скрытое специальное поле!

status,acct type,count,amount 
Processed,Savings,502,50.2 
Uncollected NSF,Checking,4299,3224.25 
Disputed,Checking,263,197.25 
Processed,Checking,11610,1161 
Uncollected NSF,Savings,433,324.75 
Declined,Checking,14,1.4 
Invalid/Closed Account,Checking,2868,2151 
Disputed,Savings,16,12 
Invalid/Closed Account,Savings,154,115.5 
------------ 
# of transactions: 20159 
processing fee: 7237.35 
+0

Что должно произойти, если у вас есть какой-то шаблон, кроме спорного, Несобранные, Invalid, обрабатываемые Отклонено? У вас нет окончательного предложения 'else', поэтому вы не добавляете' $ 3', и вы просто печатаете входные данные. Но это логическая проблема, совершенно отличная от поведения, которое вы видите, которое было рассмотрено в ответах. –

+0

Ну, я действительно должен иметь три значения .75, и все остальные умножаются на .10. Я открыт для совершенствования! –

+2

OK; поэтому отпустите второй 'if' и попробуйте' else' просто умножить на 0.10. –

ответ

2

Способ записи кода в awk будет иметь тернарное выражение, например.:

$ awk 'BEGIN{FS=OFS=","} {print $0, $2 * ($1 ~ /Processed|Declined/ ? 0.10 : 0.75)}' file 
Disputed,279,209.25 
Processed,12112,1211.2 
Uncollected NSF,4732,3549 
Declined,14,1.4 
Invalid/Closed Account,3022,2266.5 

Обратите внимание, что константы регулярных выражений разделяются / (см http://www.gnu.org/software/gawk/manual/gawk.html#Regexp), но AWK можно построить динамические регэкспы от переменных и/или строковых констант (см http://www.gnu.org/software/gawk/manual/gawk.html#Computed-Regexps), поэтому, когда Вы писали:

"/Processed|Declined/" 

в контекст подходит для динамического регулярного выражения ($1 ~ <regexp>), AWK построили регулярное выражение из него, как:

`/Processed` OR `Declined/` 

(обратите внимание буквальное / символы как часть условий регулярных выражений) вместо того, что вы хотите:

`Processed` OR `Declined` 

Вы можете видеть, что эффект здесь:

$ echo 'abc' | awk '$0 ~ /b|x/' 
abc 
$ echo 'abc' | awk '$0 ~ "/b|x/"' 
$ echo 'a/bc' | awk '$0 ~ "/b|x/"' 
a/bc 

Теперь, если вы можете понять это :

$ echo 'abc' | awk '$0 ~ "/b|x/"' 
$ echo 'abc' | awk '"/b|x/"' 
abc 

т.е. почему первый печатает ничего, кроме второго, который печатает вход.

+1

Ответ на вопрос в конце моего ответа заключается в том, что 'awk '$ 0 ~"/b | x/"'' проверяет, соответствует ли '$ 0' регулярному выражению, генерируемому из строки' '/ b | x /" ' и если это так, он будет печатать запись, но 'awk '"/b | x/"'' проверяет значение VALUE строки ''/b | x/"' и поэтому будет печатать текущую запись, если эта строка не является нуль или ноль, чего нет, независимо от значения '$ 0'. В этом втором случае awk не преобразует строку ''/b | x/"' в regexp, потому что она не знает точно, что вы хотите, чтобы она была в контексте, который она появляется, не всегда является контекстом регулярного выражения. –

2

Выпуск

Вы пропускаете соответствующий оператор ~. Это утверждение:

if ($1 "/Disputed|Uncollected|Invalid/") 

всегда истинен, потому что он проверяет, является ли конкатенация $1 с "/Disputed|Uncollected|Invalid/" не пусто - и это не так.

Попробуйте вместо этого:

if ($1 ~ /Disputed|Uncollected|Invalid/) 

Примеры

Вы можете увидеть это поведение, используя следующие остротами:

$ awk 'BEGIN { if ("" "a") { print "true" } else { print "false" }}' 
true 
$ awk 'BEGIN { if ("" "") { print "true" } else { print "false" }}' 
false 
$ awk 'BEGIN { if ("") { print "true" } else { print "false" }}' 
false 
$ awk 'BEGIN { if (RS FS "a") { print "true" } else { print "false" }}' 
true 
$ awk 'BEGIN { if (variable) { print "true" } else { print "false" }}' 
false 
$ awk 'BEGIN { var="0"; if (var) { print "true" } else { print "false" }}' 
true 
+0

С ~, я должен буду иметь имена полей $ 1. Таким образом, это означает, что Invalid/Closed Account должен быть в выражении awk, а не просто 'Invalid'. –

+0

'~' будет выполнять частичное совпадение, добавляет '. *' В начало и конец регулярного выражения. – ShellFish

2

Как сказал другой плакат, вы ушел из ~ Оператор перед первым регулярным выражением.

Кроме того, не включайте слэши в начале и в конце регулярных выражений. Либо заключите регулярные выражения в косые черты (как в Perl/Ruby/JavaScript), либо в кавычки - не оба.

if ($1 ~ "Disputed|Uncollected|Invalid") 
    $3 = $2 * .75 
else 
    if ($1 ~ "Processed|Declined") 
     $3 = $2 * 0.10 
print 
+0

Я думаю, что можно использовать косую черту: http://www.gnu.org/software/gawk/manual/gawk.html#Regexp-Patterns –

+1

Duly отметил - отредактирован, чтобы отразить это. (Извините, не проделали ничего серьезного в awk некоторое время.) – pobrelkey

+1

Избавьтесь от 'Кроме того, не включайте слэши в начале и конце ваших регулярных выражений. Либо заключите свои регулярные выражения в косые черты (как в Perl/Ruby/JavaScript), либо в кавычках - не оба. «Поскольку первое предложение на 100% неправильно, а второе - похоже на то, что 2 разделителя эквивалентны, если они не являются , Это регулярное выражение, поэтому используйте regexp delimiters '/', не заставляйте awk строить регулярное выражение из вашего текста, окруженного разделителями строк. –

Смежные вопросы