Может ли awk обрабатывать значения в записях по-разному на основе первого значения?

Lubuntu поставляется с Network-manager, что делает это очень просто. Нажмите на значок сети на панели и выберите «Изменить соединения».

В появившемся диалоговом окне выберите проводной интерфейс и нажмите «Изменить». На панели свойств IPv4 в новом диалоговом окне вы можете выбрать «Метод:« Совместно с другими компьютерами ».

Edit Network

Любое подключение к Интернету теперь будет общий для вашего проводного соединения, в комплекте с DHCP.

1
задан 26 September 2017 в 07:42

3 ответа

Во-первых, код:

#!/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

Что он делает и почему:

В задаче, которую вы пытаетесь для решения, каждый из концептуально считающихся записью является «строфой» нескольких строк, где строка может состоять из нескольких полей. Таким образом, каждая дататум имеет три «координаты»: ⟨станца,   line,   field⟩

Но фундаментальная абстракция AWK - это ⟨stanza,   line,   field field [!d8 ]. AWK по-прежнему является хорошим выбором для этой проблемы, но вам придется решить, как вы хотите сопоставить естественную абстракцию проблемы с абстракцией, которую поддерживает ваш инструмент напрямую. В вашем коде похоже, что вы можете рассматривать каждую строфу как одну запись, так как вы сделали END разделителем входных записей (RS = "END"). Это можно заставить работать, и я надеюсь, что будут опубликованы другие ответы, которые показывают, как это сделать. Но я предлагаю, чтобы awk рассматривал каждую строку как запись.

Причина в том, что есть еще один способ подумать о ваших входных данных: как список file , по одному на строку, где:

Ваша команда NAME выводит слово, следующее за ней. Концептуально это имя. Ваша команда PAY накапливает продукты в переменную total. В частности, он умножает два значения, которые следуют за ним, и увеличивает total на эту сумму. Ваша команда END печатает total, завершает линию и сбрасывает total обратно на ноль.

Как это работает, строка за строкой:

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

[d21 ] В Ubuntu awk находится в /usr/bin, а не /bin. Флаг -f требуется (на любой ОС), чтобы сообщить AWK, что следующий аргумент, который является именем файла самого сценария, должен интерпретироваться как сценарий, а не как имя входного файла для обработки.

Правило BEGIN

Вы можете сделать одно и установить в нем tally = 0, но вам не нужно, потому что AWK допускает арифметику на неинициализированных переменных и обрабатывает их как ноль. (Если вы запускали gawk --lint -f tally file, вы можете явно указать назначение, чтобы избежать предупреждения «ссылка на неинициализированную переменную».) Я помещаю здесь пустую строку, но вам не нужно.

[d26 ] Правило BEGIN

Когда первое поле NAME, напечатайте второе поле $2 как строку (%s), за которым следует пробел. [ ! d28]

$1 == "PAY" { total += $2 * $3 }

Когда первое поле PAY, увеличьте значение total произведением второго и третьего полей.

$1 == "PAY" { total += $2 * $3 }

Когда первое поле END, напечатайте значение total. Оператор print автоматически добавляет разделитель выходной записи, который является , который является именем самого скрипта , так как вы еще не установили ORS. Затем установите total на ноль, чтобы подготовиться к следующей строфе (если есть).

1
ответ дан 22 May 2018 в 18:07
  • 1
    Спасибо огромное! Это было выше и выше любого ответа, который я ожидал здесь. Также спасибо за помощь в редактировании моего вопроса, я извиняюсь, если это вызвало какую-либо путаницу (но я могу сказать по вашему отзыву, что это не слишком больно). Еще раз большое спасибо. Я думаю, что я стал намного больше знаком с awk! – Stephanie 30 September 2017 в 05:32

Во-первых, код:

#!/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

Что он делает и почему:

В задаче, которую вы пытаетесь для решения, каждый из концептуально считающихся записью является «строфой» нескольких строк, где строка может состоять из нескольких полей. Таким образом, каждая дататум имеет три «координаты»: ⟨станца, & nbsp; line, & nbsp; field⟩

Но фундаментальная абстракция AWK - это ⟨stanza, & nbsp; line, & nbsp; field field . AWK по-прежнему является хорошим выбором для этой проблемы, но вам придется решить, как вы хотите сопоставить естественную абстракцию проблемы с абстракцией, которую поддерживает ваш инструмент напрямую. В вашем коде похоже, что вы можете рассматривать каждую строфу как одну запись, так как вы сделали END разделителем входных записей (RS = "END"). Это можно заставить работать, и я надеюсь, что будут опубликованы другие ответы, которые показывают, как это сделать. Но я предлагаю, чтобы awk рассматривал каждую строку как запись.

Причина в том, что есть еще один способ подумать о ваших входных данных: как список file , по одному на строку, где:

Ваша команда NAME выводит слово, следующее за ней. Концептуально это имя. Ваша команда PAY накапливает продукты в переменную total. В частности, он умножает два значения, которые следуют за ним, и увеличивает total на эту сумму. Ваша команда END печатает total, завершает линию и сбрасывает total обратно на ноль.

Как это работает, строка за строкой:

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

В Ubuntu awk находится в /usr/bin, а не /bin. Флаг -f требуется (на любой ОС), чтобы сообщить AWK, что следующий аргумент, который является именем файла самого сценария, должен интерпретироваться как сценарий, а не как имя входного файла для обработки.

Правило BEGIN

Вы можете сделать одно и установить в нем tally = 0, но вам не нужно, потому что AWK допускает арифметику на неинициализированных переменных и обрабатывает их как ноль. (Если вы запускали gawk --lint -f tally file, вы можете явно указать назначение, чтобы избежать предупреждения «ссылка на неинициализированную переменную».) Я помещаю здесь пустую строку, но вам не нужно.

Правило BEGIN

Когда первое поле NAME, напечатайте второе поле $2 как строку (%s), за которым следует пробел. [ ! d28]

$1 == "PAY" { total += $2 * $3 }

Когда первое поле PAY, увеличьте значение total произведением второго и третьего полей.

$1 == "PAY" { total += $2 * $3 }

Когда первое поле END, напечатайте значение total. Оператор print автоматически добавляет разделитель выходной записи, который является , который является именем самого скрипта , так как вы еще не установили ORS. Затем установите total на ноль, чтобы подготовиться к следующей строфе (если есть).

1
ответ дан 18 July 2018 в 06:13

Во-первых, код:

#!/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

Что он делает и почему:

В задаче, которую вы пытаетесь для решения, каждый из концептуально считающихся записью является «строфой» нескольких строк, где строка может состоять из нескольких полей. Таким образом, каждая дататум имеет три «координаты»: ⟨станца, & nbsp; line, & nbsp; field⟩

Но фундаментальная абстракция AWK - это ⟨stanza, & nbsp; line, & nbsp; field field . AWK по-прежнему является хорошим выбором для этой проблемы, но вам придется решить, как вы хотите сопоставить естественную абстракцию проблемы с абстракцией, которую поддерживает ваш инструмент напрямую. В вашем коде похоже, что вы можете рассматривать каждую строфу как одну запись, так как вы сделали END разделителем входных записей (RS = "END"). Это можно заставить работать, и я надеюсь, что будут опубликованы другие ответы, которые показывают, как это сделать. Но я предлагаю, чтобы awk рассматривал каждую строку как запись.

Причина в том, что есть еще один способ подумать о ваших входных данных: как список file , по одному на строку, где:

Ваша команда NAME выводит слово, следующее за ней. Концептуально это имя. Ваша команда PAY накапливает продукты в переменную total. В частности, он умножает два значения, которые следуют за ним, и увеличивает total на эту сумму. Ваша команда END печатает total, завершает линию и сбрасывает total обратно на ноль.

Как это работает, строка за строкой:

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

В Ubuntu awk находится в /usr/bin, а не /bin. Флаг -f требуется (на любой ОС), чтобы сообщить AWK, что следующий аргумент, который является именем файла самого сценария, должен интерпретироваться как сценарий, а не как имя входного файла для обработки.

Правило BEGIN

Вы можете сделать одно и установить в нем tally = 0, но вам не нужно, потому что AWK допускает арифметику на неинициализированных переменных и обрабатывает их как ноль. (Если вы запускали gawk --lint -f tally file, вы можете явно указать назначение, чтобы избежать предупреждения «ссылка на неинициализированную переменную».) Я помещаю здесь пустую строку, но вам не нужно.

Правило BEGIN

Когда первое поле NAME, напечатайте второе поле $2 как строку (%s), за которым следует пробел. [ ! d28]

$1 == "PAY" { total += $2 * $3 }

Когда первое поле PAY, увеличьте значение total произведением второго и третьего полей.

$1 == "PAY" { total += $2 * $3 }

Когда первое поле END, напечатайте значение total. Оператор print автоматически добавляет разделитель выходной записи, который является , который является именем самого скрипта , так как вы еще не установили ORS. Затем установите total на ноль, чтобы подготовиться к следующей строфе (если есть).

1
ответ дан 24 July 2018 в 18:33

Другие вопросы по тегам:

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