У меня есть текстовый файл с разными данными и некоторыми денежными расходами. Я хочу искать все суммы в долларах между определенными строками и суммировать их. Конкретные строки означают поиск сумм в долларах между строками 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 может искать числа и суммировать их, но я не мог понять, как адаптировать эти предложения к моей проблеме.
Справедливо. Между определенными строками, что означает поиск между строками X и Y фразы «blah».
Вы можете использовать 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`. Никаких лишних фокусов!
Вторая причина, по которой это работает, заключается в том, что разделитель полей FS
установлен на $
. Несмотря на то, что FS
обычно является регулярным выражением, а $
явно указывает конец записи, оно содержит исключение для однобуквенных значений FS
. В этом случае $
теряет свое особое значение!
Вы действительно можете удалить часть NF==2
@Cyrus, я обновил вопрос по чьему-то предложению. Спасибо.
@ user2852381: См.: Как запустить awk для некоторого количества строк.?
В очень общем решении используется регулярное выражение с положительным ретроспективным анализом:
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 user2852381 Я добавил решение, которое учитывает только указанные строки.
Вы можете попробовать Перл
$ 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
Кодовые ответы не приветствуются. Пожалуйста, добавьте некоторое объяснение того, как это решает проблему или чем это отличается от существующих ответов. Из обзора
Являются ли количества $ всегда последними? Тоже
between specific lines
не очень понятно