Mỗi dòng chứa văn bản và số trong một cột. Tôi cần tính tổng của các số trong mỗi hàng. Làm thế nào tôi có thể làm điều đó? Cám ơn
example.log chứa:
time=31sec
time=192sec
time=18sec
time=543sec
Câu trả lời phải là 784
Mỗi dòng chứa văn bản và số trong một cột. Tôi cần tính tổng của các số trong mỗi hàng. Làm thế nào tôi có thể làm điều đó? Cám ơn
example.log chứa:
time=31sec
time=192sec
time=18sec
time=543sec
Câu trả lời phải là 784
Câu trả lời:
Với phiên bản mới hơn (4.x) của GNU awk:
awk 'BEGIN {FPAT="[0-9]+"}{s+=$1}END{print s}'
Với những awkthử khác:
awk -F '[a-z=]*' '{s+=$2}END{print s}'
s+0trong trường hợp strống, nó sẽ in 0thay vì trống.
scó thể để trống; nếu dữ liệu đầu vào không chứa dòng nào (tức là nếu không có đầu vào nào cả ). Trong trường hợp đó có hai hành vi có thể; 1) không có đầu vào => không có đầu ra hoặc 2) luôn xuất ra thứ gì đó, nếu chỉ 0. Cả hai đều là các tùy chọn hợp lý tùy thuộc vào ngữ cảnh ứng dụng. Đây +0là địa chỉ tùy chọn 2). Để giải quyết tùy chọn 1) bạn muốn viết END {if(s) print s}. - Do đó, sẽ không có ý nghĩa gì khi giả sử một trong hai tùy chọn (đối với trường hợp góc không có dữ liệu này) cho đến khi được chỉ định bởi câu hỏi.
awk -F= '{sum+=$2};END{print sum}'
time=1.4e5sec
Một GNU khác awk:
awk -v RS='[0-9]+' '{n+=RT};END{print n}'
Một perlmột:
perl -lne'$n+=$_ for/\d+/g}{print$n'
Một 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'='thay vì--field-separator =
man awkchỉ cho -F fsvà--field-separator fs
-F'='hoặc -F '='là 2 cách thực hiện -F fs(fs là "=" trong trường hợp của bạn). Tôi đã thêm các câu đơn để đảm bảo fs được nhìn thấy và giải thích chính xác bởi awk, chứ không phải shell (ví dụ nếu fs là ';' chẳng hạn)
Mọi người đã đăng awkcâu trả lời tuyệt vời , mà tôi rất thích.
Một biến thể để @cuonglm thay thế grepbằng sed:
sed 's/[^0-9]//g' example.log | paste -sd'+' - | bc
seddải tất cả mọi thứ trừ các con số.paste -sd+ -lệnh tham gia tất cả các dòng với nhau như một dòng duy nhấtbcđánh giá biểu thứcBạn nên sử dụng một máy tính.
{ tr = \ | xargs printf '[%s=]P%d+p' | dc; } <infile 2>/dev/null
Với bốn dòng của bạn in:
time=31
time=223
time=241
time=784
Và đơn giản hơn:
tr times=c ' + p' <infile |dc
... mà in ...
31
223
241
784
Nếu tốc độ là thứ bạn đang theo đuổi thì đó dclà thứ bạn muốn. Theo truyền thống, nó là bctrình biên dịch - và vẫn dành cho nhiều hệ thống.
dcgần như tôi có thể nói. Bạn đang nói về cái gì vậy?
perlv bộ công cụ unix tiêu chuẩn - thực sự không có ý nghĩa gì nếu bạn sử dụng các công cụ GNU được biên dịch trên chuỗi công cụ GNU. Tất cả sự phình to có thể ảnh hưởng tiêu cực đến hiệu suất của Perl cũng nằm trong tất cả các tiện ích GNU được biên dịch bởi GNU. Đáng buồn nhưng là sự thật. Bạn cần một bộ công cụ thực sự, được xây dựng đơn giản, đơn giản để đánh giá chính xác sự khác biệt. Ví dụ như một bộ công cụ gia truyền được liên kết tĩnh với các lib musl - theo cách đó bạn có thể điều chỉnh mô hình một công cụ / một công việc so với mô hình một công cụ để thống trị tất cả một.
Qua python3,
import re
with open(file) as f:
m = f.read()
l = re.findall(r'\d+', m)
print(sum(map(int, l)))
re.findalltrả về một danh sách các chuỗi, điều này sẽ không hoạt động
sum(int(e) for e in l)là nhiều pythonic.
Dung dịch bash tinh khiết (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.
Phiên bản ngắn:
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