Каждая строка содержит текст и цифры в одном столбце. Мне нужно рассчитать сумму чисел в каждой строке. Как я могу это сделать? Спасибо
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 '='
есть 2 способа сделать -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. Грустно, но правда. Вам нужен настоящий, просто построенный, простой набор инструментов, чтобы точно оценить разницу. Например, как набор инструментов семейной реликвии, статически связанный с мусульманскими библиотеками - таким образом, вы можете сравнить парадигму «один инструмент / одна работа» и «один инструмент, чтобы управлять ими всеми».
Через 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 (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