Кожен рядок містить текст і цифри в одному стовпчику. Мені потрібно обчислити суму чисел у кожному рядку. Як я можу це зробити? Дякую
example.log містить:
time=31sec
time=192sec
time=18sec
time=543sec
Відповідь має бути 784
Кожен рядок містить текст і цифри в одному стовпчику. Мені потрібно обчислити суму чисел у кожному рядку. Як я можу це зробити? Дякую
example.log містить:
time=31sec
time=192sec
time=18sec
time=543sec
Відповідь має бути 784
Відповіді:
З новою версією (4.x) GNU awk
:
awk 'BEGIN {FPAT="[0-9]+"}{s+=$1}END{print s}'
За допомогою іншого awk
спробуйте:
awk -F '[a-z=]*' '{s+=$2}END{print s}'
s+0
у випадку, коли s
порожній, він буде надруковано 0
замість порожнього.
s
можна пустувати; якщо вхідні дані не містять рядків (тобто якщо взагалі немає введення ). У такому випадку можливі дві поведінки; 1) немає вводу => немає виводу, або 2) завжди щось виводить, якщо тільки 0. Обидва є розумними варіантами залежно від контексту програми. Варіант +0
адресації 2). Щоб вирішити варіант 1), вам доведеться написати END {if(s) print s}
. - Тому не має сенсу припускати будь-який варіант (для цього кутового випадку відсутні дані), поки він не буде визначений питанням.
awk -F= '{sum+=$2};END{print sum}'
time=1.4e5sec
Ще один GNU awk
:
awk -v RS='[0-9]+' '{n+=RT};END{print n}'
Один perl
:
perl -lne'$n+=$_ for/\d+/g}{print$n'
POSIX один:
tr -cs 0-9 '[\n*]' | grep . | paste -sd + - | bc
sed 's/=/ /' file | awk '{ sum+=$2 } END { print sum}'
sed
awk --field-separator = '{ sum+=$2 } END { print sum}' data.dat
-F'='
замість--field-separator =
man awk
тільки дає -F fs
і--field-separator fs
-F'='
або -F '='
два способи зробити -F fs
(у вашому випадку fs - "="). Я додав сингрети, щоб переконатися, що fs належним чином бачиться & інтерпретується awk, а не оболонкою (корисно, якщо fs ';', наприклад)
Усі опублікували дивовижні awk
відповіді, які мені дуже подобаються.
Варіант @cuonglm замінюється grep
на sed
:
sed 's/[^0-9]//g' example.log | paste -sd'+' - | bc
sed
Смуги все для чисел , за винятком.paste -sd+ -
Команда об'єднує всі лінії разом в одному рядкуbc
обчислює виразСлід скористатися калькулятором.
{ tr = \ | xargs printf '[%s=]P%d+p' | dc; } <infile 2>/dev/null
Ваші чотири рядки, які друкують:
time=31
time=223
time=241
time=784
А простіше:
tr times=c ' + p' <infile |dc
... які друкує ...
31
223
241
784
Якщо швидкість - це те, що ви хочете, то dc
те, що ви хочете. Традиційно це був bc
компілятор - і досі є для багатьох систем.
dc
так близько, як я можу сказати. Про що ти говориш?
perl
на стандартний набір інструментів unix - це насправді не має особливого сенсу, якщо ви використовуєте інструменти GNU, зібрані на інструментальній ланцюзі GNU. Весь перебіг, який може негативно вплинути на продуктивність Perl, також є у всіх цих утилітах GNU, складених GNU. Сумно але правда. Вам потрібен справжній, просто побудований, простий набір інструментів, щоб точно оцінити різницю. Як, наприклад, набір інструментів для спадкоємців, статично пов'язаний з musl libs, - таким чином ви можете порівняти парадигму "один інструмент / одна робота" проти "єдиного інструмента для управління правилом".
Через python3,
import re
with open(file) as f:
m = f.read()
l = re.findall(r'\d+', m)
print(sum(map(int, l)))
re.findall
повертає список рядків, це не буде працювати
sum(int(e) for e in l)
є більш пітонічним.
Чистий розчин башу (Bash 3+):
while IFS= read -r line; do # While it reads a line:
if [[ "$line" =~ [0-9]+ ]]; then # If the line contains numbers:
((counter+=BASH_REMATCH[0])) # Add the current number to counter
fi # End if.
done # End loop.
echo "Total number: $counter" # Print the number.
unset counter # Reset counter to 0.
Коротка версія:
while IFS= read -r l; do [[ "$l" =~ [0-9]+ ]] && ((c+=BASH_REMATCH)); done; echo $c; c=0
PS4='$((x+=${time%s*}))' time=0 x=0 sh -x <infile