Поиск количеств в определенных строках текстового файла и суммы

У меня есть текстовый файл с разными данными и некоторыми денежными расходами. Я хочу искать все суммы в долларах между определенными строками и суммировать их. Конкретные строки означают поиск сумм в долларах между строками 6 и 8.

Вот пример моего текстового файла:

Mary had a little $5.00 lamb
Bing bang bow

Blah blah blah

STARBUCKS Jan 8th, 2019 $7.00
MCDONALD'S Jan 10th, 2019 $6.00
UBER Jan 11th, 2019 $20.01

Ожидаемый ответ: $33,01.

Я обнаружил, что в VI я могу искать суммы в долларах следующим образом:

/$\d\{2}\|\$\d\{1}

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

Являются ли количества $ всегда последними? Тоже between specific lines не очень понятно

sjsam 09.04.2019 20:38

Справедливо. Между определенными строками, что означает поиск между строками X и Y фразы «blah».

user2852381 10.04.2019 02:59
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
66
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вы можете использовать awk с некоторым сопоставлением с образцом:

awk '$NF ~/^\$.*$/{amt+=substr($NF,2)}END{print "$" amt}' file
$33.01
Ответ принят как подходящий

Используйте $ в качестве разделителя полей. Если есть второй столбец (NF==2), суммируйте значения во втором столбце.

awk -F '$' 'NF==2{sum+=$2} END{print sum}' file

Это прекрасно работает, потому что awk преобразует строки в числа, используя strtod. Функция по существу игнорирует начальные пробелы, считывает следующую часть как число, а все нераспознанные символы игнорируются. Таким образом, если во втором поле указано 3456.89 cost of potatoes', the operation sum+=$2`, $2 будет преобразовано в числовое значение 3456,89`. Никаких лишних фокусов!

kvantour 09.04.2019 23:38

Вторая причина, по которой это работает, заключается в том, что разделитель полей FS установлен на $. Несмотря на то, что FS обычно является регулярным выражением, а $ явно указывает конец записи, оно содержит исключение для однобуквенных значений FS. В этом случае $ теряет свое особое значение!

kvantour 09.04.2019 23:46

Вы действительно можете удалить часть NF==2

kvantour 09.04.2019 23:47

@Cyrus, я обновил вопрос по чьему-то предложению. Спасибо.

user2852381 10.04.2019 03:30

В очень общем решении используется регулярное выражение с положительным ретроспективным анализом:

grep -oP --regexp='(?<=\$)[0-9\.]*' inputFile | paste -s -d+ | bc

Регулярное выражение (?<=\$)[0-9\.]* соответствует только последовательностям цифр и '.' если им предшествует '$'

Модифицированное решение с использованием awk выглядит так:

grep -oP --regexp='(?<=\$)[0-9\.]*' inputFile | awk '{s+=$1} END {print s}'

Обе команды возвращают 33.01

Чтобы ограничить суммирование указанными строками, вы можете добавить awk 'NR>5 && NR<9{print $0}':

awk 'NR>5 && NR<9{print $0}' inputFile | grep -oP --regexp='(?<=\$)[0-9\.]*' | awk '{s+=$1} END {print s}'

Ф. Кнорр, я обновил вопрос по чьему-то предложению. Спасибо.

user2852381 10.04.2019 03:31

@user2852381 user2852381 Я добавил решение, которое учитывает только указанные строки.

F. Knorr 11.04.2019 22:56

Вы можете попробовать Перл

$ perl -ne ' /\$(\S+)/ and $sum+=$1 ; END { print $sum } ' quantile.txt
38.01

данный ввод

$ cat quantile.txt
Mary had a little $5.00 lamb
Bing bang bow

Blah blah blah

STARBUCKS Jan 8th, 2019 $7.00
MCDONALD'S Jan 10th, 2019 $6.00
UBER Jan 11th, 2019 $20.01

если ваши данные в 'd'

 perl -ne 'BEGIN{$s=0} if ($.>=6) {/\$([\d.]+)/; $s+=$1} END{print "total=$s"}' d

Кодовые ответы не приветствуются. Пожалуйста, добавьте некоторое объяснение того, как это решает проблему или чем это отличается от существующих ответов. Из обзора

Nick 13.04.2019 06:22

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