Я относительно плохо знаком с awk. Я создаю awk сценарий, который считает файл, который имеет общий формат:
NAME firstName lastName
PAY cost numberOfPayments
END
Мой файл будет выглядеть примерно так:
NAME Jane Doe
PAY 5.00 2
PAY 2.00 10
END
NAME John Doe
PAY 10.00 5
PAY 4.00 3
PAY 1.00 20
END
И сумма платежей между NAME
кому: END
может варьироваться, и может быть несколько имен (это - просто образец).
Это - мой awk сценарий:
# !/bin/awk
BEGIN { total=0; RS = "END"; }
{
if (match($1, "NAME")) {
print $2;
}
if (match($1, "SAVE")) {
total = total + ($2 * $3);
print total;
}
}
Первое значение должно распознать, какое действие мы формуем (PAY
по сравнению с. NAME
). На основе этого я должен или распечатать NAME
или найдите общую сумму, которая найдена путем умножения стоимости количеством платежей. END
то, что я использую, чтобы показать, что это - конец записи для того определенного клиента.
Вывод этого конкретного файла должен быть:
Jane 30
John 82
Я попробовал несколько путей, но я, может казаться, не получаю желаемый вывод. Любая справка для получения этой работы очень ценилась бы!
#!/usr/bin/awk -f
$1 == "NAME" { printf "%s ", $2 }
$1 == "PAY" { total += $2 * $3 }
$1 == "END" { print total; total = 0 }
Если Вы называете сценарий tally
, отметьте его исполняемый файл с chmod +x tally
, и Вы находитесь в каталоге, который содержит его, можно выполнить его на входном файле file
с:
./tally file
На входном тексте Вы показали, он дает вывод, который Вы хотели:
Jane 30
John 82
Вы не заявили, на что Вы хотите, чтобы вывод был похож, когда существует несколько имен без END
промежуточный, но я предполагаю, что Вы хотите произвести имя для каждого. Рассмотрите этот входной файл:
NAME Jane Doe
NAME Clark Kent
PAY 5.77 9
END
NAME John Doe
PAY 14.22 6
NAME Linda Lee Danvers
PAY .25 4
END
Это производит этот вывод:
Jane Clark 51.93
John Linda 86.32
В проблеме Вы пытаетесь решить, каждое из того, что должно концептуально думаться, поскольку запись является "строкой файла конфигурации" нескольких строк, где строка может состоять из нескольких полей. Каждая данная величина поэтому имеет три "координаты": ⟨stanza, строка, поле ⟩
Но фундаментальная абстракция AWK вместо этого ⟨record, поле ⟩. AWK является все еще хорошим выбором для этой проблемы, но необходимо будет решить, как Вы хотите отобразить естественную абстракцию проблемы к абстракции Ваши поддержки инструмента непосредственно. В Вашем коде похоже, что можно пытаться рассматривать каждую строку файла конфигурации как единственную запись, так как Вы сделали END
входной разделитель записей (RS = "END"
). Это может быть сделано работать, и я надеюсь, что другие ответы отправляются то шоу как. Но я предлагаю иметь awk
рассматривайте каждую строку как запись вместо этого.
Причина состоит в том, что уже существует другой способ думать о Ваших входных данных: как список команд, один на строку, где:
NAME
команда производит слово, которое следует за нею. Концептуально это - имя.PAY
команда накапливает продукты в переменную total
. А именно, это умножает два значения, которые следуют за ним и увеличения total
той суммой.END
печать команды total
, заканчивает строку и сброс total
назад обнулять.#!/usr/bin/awk -f
В Ubuntu, awk
расположен в /usr/bin
и нет /bin
. -f
флаг требуется (на любой ОС) сказать AWK, что следующий аргумент, который является именем файла самого сценария, должен быть интерпретирован как сценарий, а не как название входного файла для обработки.
Нет BEGIN
правило
Вы могли сделать один и установить tally = 0
в нем, но Вам не нужно к тому, потому что AWK позволяет арифметику на неинициализированных переменных и рассматривает их как нуль. (Если Вы работали gawk --lint -f tally file
затем Вы могли бы хотеть включать присвоение явно для предотвращения "ссылки на неинициализированную переменную" предупреждение.) Я поместил пустую строку здесь, но Вы не имеете к.
$1 == "NAME" { printf "%s ", $2 }
Когда первое поле NAME
, распечатайте второе поле $2
как строка (%s
) сопровождаемый пространством.
$1 == "PAY" { total += $2 * $3 }
Когда первое поле PAY
, увеличьте значение total
продуктом вторых и третьих полей.
$1 == "END" { print total; total = 0 }
Когда первое поле END
, распечатайте значение total
. print
оператор автоматически добавляет выходной разделитель записей, который является новой строкой, так как Вы не установили ORS
иначе. Затем набор total
назад обнулять для подготовки к следующей строке файла конфигурации (если таковые имеются).