Lệnh Shell để tính tổng số nguyên, mỗi dòng trên một dòng?


867

Tôi đang tìm kiếm một lệnh sẽ chấp nhận (làm đầu vào) nhiều dòng văn bản, mỗi dòng chứa một số nguyên duy nhất và xuất tổng của các số nguyên này.

Một chút về nền tảng, tôi có một tệp nhật ký bao gồm các phép đo thời gian. Thông qua việc grepping cho các dòng có liên quan và một chút sedđịnh dạng lại, tôi có thể liệt kê tất cả các thời gian trong tập tin đó. Tôi muốn làm việc ra tổng số. Tôi có thể chuyển đầu ra trung gian này tới bất kỳ lệnh nào để thực hiện tổng cuối cùng. Tôi đã luôn sử dụng exprtrong quá khứ, nhưng trừ khi nó chạy ở chế độ RPN, tôi không nghĩ rằng nó sẽ đối phó với điều này (và thậm chí sau đó nó sẽ rất khó khăn).

Làm thế nào tôi có thể có được tổng các số nguyên?


2
Điều này rất giống với một câu hỏi tôi đã hỏi cách đây một thời gian: stackoverflow.com/questions/295781/iêu
An̲̳̳drew

5
Tôi thực sự thích câu hỏi này vì thực tế là có rất nhiều câu trả lời đúng (hoặc ít nhất là có hiệu quả).
Francisco Canedo

Câu hỏi này cảm thấy như một vấn đề cho mã golf. codegolf.stackexchange.com :)
Gordon Bean

Câu trả lời:


1322

Bit của awk nên làm gì?

awk '{s+=$1} END {print s}' mydatafile

Lưu ý: một số phiên bản của awk có một số hành vi kỳ quặc nếu bạn định thêm bất cứ thứ gì vượt quá 2 ^ 31 (2147483647). Xem bình luận để có thêm nền tảng. Một gợi ý là sử dụng printfchứ không phải print:

awk '{s+=$1} END {printf "%.0f", s}' mydatafile

7
Có rất nhiều tình yêu awk trong căn phòng này! Tôi thích cách một tập lệnh đơn giản như thế này có thể được sửa đổi để thêm cột dữ liệu thứ hai chỉ bằng cách thay đổi $ 1 thành $ 2
Paul Dixon

2
Không có giới hạn thực tế, vì nó sẽ xử lý đầu vào dưới dạng luồng. Vì vậy, nếu nó có thể xử lý một tệp của các dòng X, bạn có thể khá chắc chắn rằng nó có thể xử lý X + 1.
Paul Dixon

4
Tôi đã từng viết một bộ xử lý danh sách gửi thư thô sơ với một kịch bản awk chạy qua tiện ích kỳ nghỉ. Thời gian tốt. :)
LS

2
chỉ sử dụng điều này cho một tập lệnh: đếm tất cả các trang của tài liệu:ls $@ | xargs -i pdftk {} dump_data | grep NumberOfPages | awk '{s+=$2} END {print s}'
cừu bay

8
Hãy cẩn thận, nó sẽ không hoạt động với các số lớn hơn 2147483647 (tức là 2 ^ 31), vì awk sử dụng biểu diễn số nguyên có chữ ký 32 bit. Sử dụng awk '{s+=$1} END {printf "%.0f", s}' mydatafilethay thế.
Giancarlo Sportelli

665

Dán thường hợp nhất các dòng của nhiều tệp, nhưng nó cũng có thể được sử dụng để chuyển đổi các dòng riêng lẻ của một tệp thành một dòng duy nhất. Cờ phân cách cho phép bạn truyền phương trình loại x + x cho bc.

paste -s -d+ infile | bc

Ngoài ra, khi đường ống từ stdin,

<commands> | paste -s -d+ - | bc

1
Rất đẹp! Tôi đã đặt một khoảng trắng trước dấu "+", chỉ để giúp tôi phân tích cú pháp tốt hơn, nhưng điều đó rất thuận tiện cho việc chuyển một số số bộ nhớ thông qua dán và sau đó bc.
Michael H.

73
Dễ nhớ và gõ hơn nhiều so với giải pháp awk. Ngoài ra, lưu ý rằng pastecó thể sử dụng dấu gạch ngang -làm tên tệp - sẽ cho phép bạn chuyển các số từ đầu ra của lệnh thành đầu ra tiêu chuẩn của dán mà không cần phải tạo tệp trước:<commands> | paste -sd+ - | bc
George

19
Tôi có một tập tin với 100 triệu số. Lệnh awk mất 21 giây; lệnh dán mất 41 giây. Nhưng tốt để đáp ứng 'dán' tuy nhiên!
Abhi

4
@ Abhi: Thú vị: DI đoán tôi sẽ mất 20 năm để tìm ra lệnh awk để nó phát triển mặc dù cho đến khi tôi thử 100 triệu và một số: D
Mark K Cowan

6
@George Bạn có thể rời khỏi -, mặc dù. (Nó rất hữu ích nếu bạn muốn kết hợp một tệp với stdin).
Alois Mahdal

128

Phiên bản một lớp trong Python:

$ python -c "import sys; print(sum(int(l) for l in sys.stdin))"

Trên một lớp lót không hoạt động đối với các tệp trong sys.argv [], nhưng tệp này có stackoverflow.com/questions/450799/iêu
jfs

Đúng vậy - tác giả nói rằng anh ta sẽ chuyển đầu ra từ một kịch bản khác vào lệnh và tôi đã cố gắng làm cho nó ngắn nhất có thể :)
dF.

39
Phiên bản ngắn hơn sẽ làpython -c"import sys; print(sum(map(int, sys.stdin)))"
jfs

4
Tôi thích câu trả lời này vì dễ đọc và linh hoạt. Tôi cần kích thước trung bình của các tệp nhỏ hơn 10Mb trong một bộ sưu tập các thư mục và sửa đổi nó thành:find . -name '*.epub' -exec stat -c %s '{}' \; | python -c "import sys; nums = [int(n) for n in sys.stdin if int(n) < 10000000]; print(sum(nums)/len(nums))"
Paul Whipp

1
Bạn cũng có thể lọc ra các số không nếu bạn có một số văn bản được trộn vào:import sys; print(sum(int(''.join(c for c in l if c.isdigit())) for l in sys.stdin))
Granitosaurus

91

Tôi sẽ đặt một CẢNH BÁO lớn cho giải pháp thường được phê duyệt:

awk '{s+=$1} END {print s}' mydatafile # DO NOT USE THIS!!

đó là bởi vì trong hình thức này, awk sử dụng biểu diễn số nguyên có chữ ký 32 bit: nó sẽ tràn cho các khoản tiền vượt quá 2147483647 (tức là, 2 ^ 31).

Một câu trả lời tổng quát hơn (để tính tổng các số nguyên) sẽ là:

awk '{s+=$1} END {printf "%.0f\n", s}' mydatafile # USE THIS INSTEAD

Tại sao printf () giúp ở đây? Việc tràn int sẽ xảy ra trước đó bởi vì mã tổng hợp là như nhau.
Robert Klemme 10/03/2015

9
Bởi vì vấn đề thực sự nằm ở chức năng "in". Awk sử dụng số nguyên 64 bit, nhưng vì một số lý do, in ra sẽ tăng chúng lên 32 bit.
Giancarlo Sportelli

4
Lỗi in dường như đã được sửa, ít nhất là cho awk 4.0.1 & bash 4.3.11, trừ khi tôi nhầm: echo -e "2147483647 \n 100" |awk '{s+=$1}END{print s}'chương trình2147483747
Xen2050

4
Sử dụng phao chỉ giới thiệu một vấn đề mới: echo 999999999999999999 | awk '{s+=$1} END {printf "%.0f\n", s}'sản xuất1000000000000000000
Patrick

1
Không nên chỉ sử dụng "% ld" trên các hệ thống 64 bit để không bị cắt xén thành 32 bit? Như @Patrick chỉ ra, phao không phải là một ý tưởng tuyệt vời ở đây.
yerforkferchips

78

Bash đơn giản:

$ cat numbers.txt 
1
2
3
4
5
6
7
8
9
10
$ sum=0; while read num; do ((sum += num)); done < numbers.txt; echo $sum
55


@rjack, được numđịnh nghĩa ở đâu? Tôi tin rằng bằng cách nào đó nó được kết nối với < numbers.txtbiểu thức, nhưng không rõ làm thế nào.
Vào

66
dc -f infile -e '[+z1<r]srz1<rp'

Lưu ý rằng các số âm có tiền tố với dấu trừ nên được dịch cho dc, vì nó sử dụng _tiền tố thay vì -tiền tố cho điều đó. Ví dụ, thông qua tr '-' '_' | dc -f- -e '...'.

Chỉnh sửa: Vì câu trả lời này đã nhận được rất nhiều phiếu "cho sự tối nghĩa", đây là một lời giải thích chi tiết:

Biểu thức [+z1<r]srz1<rp thực hiện như sau :

[   interpret everything to the next ] as a string
  +   push two values off the stack, add them and push the result
  z   push the current stack depth
  1   push one
  <r  pop two values and execute register r if the original top-of-stack (1)
      is smaller
]   end of the string, will push the whole thing to the stack
sr  pop a value (the string above) and store it in register r
z   push the current stack depth again
1   push 1
<r  pop two values and execute register r if the original top-of-stack (1)
    is smaller
p   print the current top-of-stack

Như mã giả:

  1. Xác định "add_top_of_stack" là:
    1. Xóa hai giá trị trên cùng khỏi ngăn xếp và thêm kết quả trở lại
    2. Nếu ngăn xếp có hai hoặc nhiều giá trị, hãy chạy "add_top_of_stack" theo cách đệ quy
  2. Nếu ngăn xếp có hai hoặc nhiều giá trị, hãy chạy "add_top_of_stack"
  3. In kết quả, bây giờ là mục duy nhất còn lại trong ngăn xếp

Để thực sự hiểu được sự đơn giản và sức mạnh của dc, đây là một kịch bản Python đang hoạt động thực hiện một số lệnh từ dcvà thực thi một phiên bản Python của lệnh trên:

### Implement some commands from dc
registers = {'r': None}
stack = []
def add():
    stack.append(stack.pop() + stack.pop())
def z():
    stack.append(len(stack))
def less(reg):
    if stack.pop() < stack.pop():
        registers[reg]()
def store(reg):
    registers[reg] = stack.pop()
def p():
    print stack[-1]

### Python version of the dc command above

# The equivalent to -f: read a file and push every line to the stack
import fileinput
for line in fileinput.input():
    stack.append(int(line.strip()))

def cmd():
    add()
    z()
    stack.append(1)
    less('r')

stack.append(cmd)
store('r')
z()
stack.append(1)
less('r')
p()

2
dc chỉ là công cụ lựa chọn để sử dụng. Nhưng tôi sẽ làm điều đó với ops stack ít hơn một chút. Giả sử rằng tất cả các dòng thực sự chứa một số : (echo "0"; sed 's/$/ +/' inp; echo 'pq')|dc.
ikrabbe

5
Các thuật toán trực tuyến : dc -e '0 0 [+?z1<m]dsmxp'. Vì vậy, chúng tôi không lưu tất cả các số trên ngăn xếp trước khi xử lý mà đọc và xử lý từng số một (chính xác hơn, từng dòng một, vì một dòng có thể chứa nhiều số). Lưu ý rằng dòng trống có thể chấm dứt một chuỗi đầu vào.
ruvim

@ikrabbe thật tuyệt. Nó thực sự có thể được rút ngắn bởi một ký tự nữa: không gian trong sedthay thế có thể được loại bỏ, vì dc không quan tâm đến khoảng trắng giữa các đối số và toán tử. (echo "0"; sed 's/$/+/' inputFile; echo 'pq')|dc
WhiteHotLoveTiger

58

Với jq :

seq 10 | jq -s 'add' # 'add' is equivalent to 'reduce .[] as $item (0; . + $item)'

7
Tôi thích điều này bởi vì tôi đoán nó rất rõ ràng và ngắn đến mức tôi thực sự có thể nhớ nó.
Alfe

46

Bash tinh khiết và ngắn.

f=$(cat numbers.txt)
echo $(( ${f//$'\n'/+} ))

9
Đây là giải pháp tốt nhất vì nó không tạo ra bất kỳ quy trình con nào nếu bạn thay thế dòng đầu tiên bằng f=$(<numbers.txt).
loentar

1
bất kỳ cách nào có đầu vào từ stdin? như từ một đường ống?
njzk2

@ njzk2 Nếu bạn đặt f=$(cat); echo $(( ${f//$'\n'/+} ))một tập lệnh, thì bạn có thể chuyển bất cứ thứ gì sang tập lệnh đó hoặc gọi nó mà không có đối số cho đầu vào stdin tương tác (chấm dứt với Control-D).
mkuity0

5
@loentar Đây <numbers.txtlà một cải tiến, nhưng, về tổng thể, giải pháp này chỉ hiệu quả đối với các tệp đầu vào nhỏ; chẳng hạn, với một tệp gồm 1.000 dòng đầu vào, awkgiải pháp được chấp nhận nhanh hơn khoảng 20 lần trên máy của tôi - và cũng tiêu tốn ít bộ nhớ hơn, vì tệp không được đọc cùng một lúc.
mkuity0

2
Tôi đã gần như mất hy vọng khi tôi đạt được điều này. Bash tinh khiết!
Omer Akhter

37
perl -lne '$x += $_; END { print $x; }' < infile.txt

4
Và tôi đã thêm chúng trở lại: "-l" đảm bảo rằng đầu ra được chấm dứt dưới dạng shell `` backticks và hầu hết các chương trình mong đợi, và "<" cho biết lệnh này có thể được sử dụng trong một đường ống.
j_random_hacker

Bạn đúng rồi. Như một cái cớ: Mỗi nhân vật trong Perl one-liners đòi hỏi một công việc trí óc đối với tôi, do đó tôi thích lột càng nhiều nhân vật càng tốt. Thói quen có hại trong trường hợp này.
jfs

2
Một trong số ít giải pháp không tải mọi thứ vào RAM.
Erik Aronesty

28

Mười lăm xu của tôi:

$ cat file.txt | xargs  | sed -e 's/\ /+/g' | bc

Thí dụ:

$ cat text
1
2
3
3
4
5
6
78
9
0
1
2
3
4
576
7
4444
$ cat text | xargs  | sed -e 's/\ /+/g' | bc 
5148

Đầu vào của tôi có thể chứa các dòng trống, vì vậy tôi đã sử dụng những gì bạn đã đăng ở đây cộng với a grep -v '^$'. Cảm ơn!
James Oravec

ồ !! Câu trả lời của bạn thật tuyệt vời! yêu thích cá nhân của tôi từ tất cả trong
guồng

Yêu cái này và +1 cho đường ống dẫn. Giải pháp rất đơn giản và dễ dàng cho tôi
Gelin Luo

24

Tôi đã thực hiện một điểm chuẩn nhanh về các câu trả lời hiện có

  • chỉ sử dụng các công cụ tiêu chuẩn (xin lỗi cho những thứ như luahoặc rocket),
  • là một lớp lót thực sự,
  • có khả năng thêm số lượng lớn (100 triệu) và
  • rất nhanh (tôi bỏ qua những cái mất nhiều hơn một phút).

Tôi luôn thêm các con số từ 1 đến 100 triệu có thể thực hiện được trên máy của mình trong chưa đầy một phút cho một số giải pháp.

Đây là kết quả:

Con trăn

:; seq 100000000 | python -c 'import sys; print sum(map(int, sys.stdin))'
5000000050000000
# 30s
:; seq 100000000 | python -c 'import sys; print sum(int(s) for s in sys.stdin)'
5000000050000000
# 38s
:; seq 100000000 | python3 -c 'import sys; print(sum(int(s) for s in sys.stdin))'
5000000050000000
# 27s
:; seq 100000000 | python3 -c 'import sys; print(sum(map(int, sys.stdin)))'
5000000050000000
# 22s
:; seq 100000000 | pypy -c 'import sys; print(sum(map(int, sys.stdin)))'
5000000050000000
# 11s
:; seq 100000000 | pypy -c 'import sys; print(sum(int(s) for s in sys.stdin))'
5000000050000000
# 11s

Awk

:; seq 100000000 | awk '{s+=$1} END {print s}'
5000000050000000
# 22s

Dán & Bc

Điều này đã hết bộ nhớ trên máy của tôi. Nó hoạt động với một nửa kích thước của đầu vào (50 triệu số):

:; seq 50000000 | paste -s -d+ - | bc
1250000025000000
# 17s
:; seq 50000001 100000000 | paste -s -d+ - | bc
3750000025000000
# 18s

Vì vậy, tôi đoán nó sẽ mất ~ 35 giây cho 100 triệu số.

Perl

:; seq 100000000 | perl -lne '$x += $_; END { print $x; }'
5000000050000000
# 15s
:; seq 100000000 | perl -e 'map {$x += $_} <> and print $x'
5000000050000000
# 48s

Hồng ngọc

:; seq 100000000 | ruby -e "puts ARGF.map(&:to_i).inject(&:+)"
5000000050000000
# 30s

C

Chỉ để so sánh, tôi đã biên soạn phiên bản C và cũng đã thử nghiệm điều này, chỉ để có ý tưởng về các giải pháp dựa trên công cụ chậm hơn bao nhiêu.

#include <stdio.h>
int main(int argc, char** argv) {
    long sum = 0;
    long i = 0;
    while(scanf("%ld", &i) == 1) {
        sum = sum + i;
    }
    printf("%ld\n", sum);
    return 0;
}

 

:; seq 100000000 | ./a.out 
5000000050000000
# 8s

Phần kết luận

C tất nhiên là nhanh nhất với 8 giây , nhưng giải pháp Pypy chỉ thêm rất ít chi phí khoảng 30% đến 11 giây . Nhưng, công bằng mà nói, Pypy không chính xác theo tiêu chuẩn. Hầu hết mọi người chỉ cài đặt CPython chậm hơn đáng kể (22s), nhanh chính xác như giải pháp Awk phổ biến.

Giải pháp nhanh nhất dựa trên các công cụ tiêu chuẩn là Perl (15 giây).


2
Cách tiếp cận paste+ bcchỉ là những gì tôi đang tìm kiếm để tính tổng các giá trị hex, cảm ơn!
Tomislav Nakic-Alfirevic

1
Chỉ để cho vui, ở Rust:use std::io::{self, BufRead}; fn main() { let stdin = io::stdin(); let mut sum: i64 = 0; for line in stdin.lock().lines() { sum += line.unwrap().parse::<i64>().unwrap(); } println!("{}", sum); }
Jocelyn

câu trả lời tuyệt vời. không phải với nitpick nhưng đó là trường hợp nếu bạn quyết định đưa vào những kết quả dài hơn đó, câu trả lời sẽ còn tuyệt vời hơn nữa!
Steven Lu

@StevenLu Tôi cảm thấy câu trả lời sẽ dài hơn và do đó ít tuyệt vời hơn (để sử dụng từ ngữ của bạn). Nhưng tôi có thể hiểu rằng cảm giác này không cần phải được chia sẻ bởi mọi người :)
Alfe

Tiếp theo: numba + song song
gerrit

17

Plain bash một lót

$ cat > /tmp/test
1 
2 
3 
4 
5
^D

$ echo $(( $(cat /tmp/test | tr "\n" "+" ) 0 ))

7
Không cần mèo : echo $(( $( tr "\n" "+" < /tmp/test) 0 ))
agc

2
trkhông chính xác là "Bash đơn giản" / nitpick
Benjamin W.

17

Giải pháp BASH, nếu bạn muốn biến điều này thành một lệnh (ví dụ: nếu bạn cần thực hiện việc này thường xuyên):

addnums () {
  local total=0
  while read val; do
    (( total += val ))
  done
  echo $total
}

Sau đó sử dụng:

addnums < /tmp/nums

14

Tôi nghĩ AWK là những gì bạn đang tìm kiếm:

awk '{sum+=$1}END{print sum}'

Bạn có thể sử dụng lệnh này bằng cách chuyển danh sách số qua đầu vào tiêu chuẩn hoặc bằng cách chuyển tệp chứa các số làm tham số.



11

Các công việc sau đây trong bash:

I=0

for N in `cat numbers.txt`
do
    I=`expr $I + $N`
done

echo $I

1
Mở rộng lệnh nên được sử dụng một cách thận trọng khi các tệp có thể lớn tùy ý. Với số.txt là 10MB, cat numbers.txtbước này sẽ có vấn đề.
Giacomo

1
Thật vậy, tuy nhiên (nếu không có giải pháp tốt hơn được tìm thấy ở đây) tôi sẽ sử dụng giải pháp này cho đến khi tôi thực sự gặp phải vấn đề đó.
Francisco Canedo

11

Bạn có thể sử dụng num-utils, mặc dù nó có thể quá mức cho những gì bạn cần. Đây là một bộ các chương trình để thao tác các số trong trình bao và có thể thực hiện một số điều tiện lợi, bao gồm cả việc thêm chúng vào. Hơi lỗi thời một chút, nhưng chúng vẫn hoạt động và có thể hữu ích nếu bạn cần làm gì đó nhiều hơn.

http://suso.suso.org/programs/num-utils/


Ví dụ : numsum numbers.txt.
agc

9

Tôi nhận ra đây là một câu hỏi cũ, nhưng tôi thích giải pháp này đủ để chia sẻ nó.

% cat > numbers.txt
1 
2 
3 
4 
5
^D
% cat numbers.txt | perl -lpe '$c+=$_}{$_=$c'
15

Nếu có hứng thú, tôi sẽ giải thích cách nó hoạt động.


10
Xin đừng. Chúng tôi muốn giả vờ rằng -n và -p là những thứ ngữ nghĩa tốt đẹp, không chỉ là một chuỗi dán thông minh;)
hobbs

2
Vâng làm ơn, hãy giải thích :) (Tôi không phải là một anh chàng đánh máy Perl.)
Jens

1
Hãy thử chạy "perl -MO = Depough -lpe '$ c + = $ _} {$ _ = $ c'" và nhìn vào đầu ra, về cơ bản -l sử dụng dòng mới và cả dấu tách đầu vào và đầu ra, và -p in từng dòng. Nhưng để thực hiện '-p', trước tiên, perl thêm một số tấm nồi hơi (mà -MO = Depzzy) sẽ hiển thị cho bạn, nhưng sau đó nó chỉ thay thế và biên dịch. Do đó, bạn có thể khiến một khối bổ sung được chèn bằng phần '} {' và lừa nó không in trên mỗi dòng, nhưng in ở cuối.
Nym

9

Bash tinh khiết và trong một lớp lót :-)

$ cat numbers.txt
1
2
3
4
5
6
7
8
9
10


$ I=0; for N in $(cat numbers.txt); do I=$(($I + $N)); done; echo $I
55

Tại sao có hai ((dấu ngoặc đơn ))?
Vào

Không thực sự bash tinh khiết do con mèo. làm cho nó thuần túy bằng cách thay thế con mèo bằng$(< numbers.txt)
Dani_l


6

Perl thuần thay thế, khá dễ đọc, không yêu cầu gói hoặc tùy chọn:

perl -e "map {$x += $_} <> and print $x" < infile.txt

hoặc ngắn hơn một chút: perl -e 'map {$ x + = $ _} <>; in $ x 'infile.txt
Avi Tevet

Bộ nhớ cần có gần 2GB cho đầu vào lớn 10 triệu số
Amit N Nikol

6

Dành cho những người yêu thích Ruby

ruby -e "puts ARGF.map(&:to_i).inject(&:+)" numbers.txt

5

Không thể tránh gửi điều này:

jot 1000000 | sed '2,$s/$/+/;$s/$/p/' | dc

Nó được tìm thấy ở đây:
Hầu hết các lớp vỏ unix thanh lịch để tổng hợp danh sách các số chính xác tùy ý?

Và đây là những ưu điểm đặc biệt của nó so với awk, bc và bạn bè:

  • nó không phụ thuộc vào bộ đệm và do đó không bị nghẹt với đầu vào thực sự lớn
  • nó ngụ ý không có độ chính xác cụ thể - kích thước số nguyên cho giới hạn đó
  • không cần mã khác, nếu cần thêm số dấu phẩy động

Vui lòng bao gồm mã liên quan đến câu hỏi trong câu trả lời và không tham khảo một liên kết
Ibo

5

Sử dụng GNU datamash util :

seq 10 | datamash sum 1

Đầu ra:

55

Nếu dữ liệu đầu vào không đều, có khoảng trắng và tab ở những vị trí kỳ lạ, điều này có thể gây nhầm lẫn datamash, sau đó sử dụng công -Wtắc:

<commands...> | datamash -W sum 1

... hoặc sử dụng trđể dọn sạch khoảng trắng:

<commands...> | tr -d '[[:blank:]]' | datamash sum 1


3

Bạn có thể làm điều đó trong python, nếu bạn cảm thấy thoải mái:

Không được kiểm tra, chỉ cần gõ:

out = open("filename").read();
lines = out.split('\n')
ints = map(int, lines)
s = sum(ints)
print s

Sebastian chỉ ra một kịch bản lót:

cat filename | python -c"from fileinput import input; print sum(map(int, input()))"

python -c "từ nhập dữ liệu nhập tệp; in tổng (map (int, input ()))" Numbers.txt
jfs

2
mèo bị lạm dụng, chuyển hướng stdin từ tệp: python -c "..." <Numbers.txt
Giacomo

2
@rjack: catđược sử dụng để chứng minh rằng tập lệnh hoạt động cả cho stdin và cho các tệp trong argv [] (như while(<>)trong Perl). Nếu đầu vào của bạn nằm trong một tệp thì '<' là không cần thiết.
jfs

2
Nhưng < numbers.txtchứng tỏ rằng nó hoạt động trên stdin cũng như cat numbers.txt |làm. Và nó không dạy những thói quen xấu.
Xiong Chiamiov

3
$ mèo n
2
4
2
7
số 8
9
$ perl -MList::Util -le 'print List::Util::sum(<>)' < n
32

Hoặc, bạn có thể nhập các số trên dòng lệnh:

$ perl -MList::Util -le 'print List::Util::sum(<>)'
1
3
5
^D
9

Tuy nhiên, cái này làm lu mờ tệp nên không nên sử dụng trên các tệp lớn. Xem câu trả lời của j_random_hacker mà tránh bị nhếch nhác .


3

Mục sau sẽ hoạt động (giả sử số của bạn là trường thứ hai trên mỗi dòng).

awk 'BEGIN {sum=0} \
 {sum=sum + $2} \
END {print "tot:", sum}' Yourinputfile.txt

2
Bạn không thực sự cần phần {sum = 0}
Uphill_ What '1

3

Một lớp lót trong vợt:

racket -e '(define (g) (define i (read)) (if (eof-object? i) empty (cons i (g)))) (foldr + 0 (g))' < numlist.txt

3

C (không đơn giản hóa)

seq 1 10 | tcc -run <(cat << EOF
#include <stdio.h>
int main(int argc, char** argv) {
    int sum = 0;
    int i = 0;
    while(scanf("%d", &i) == 1) {
        sum = sum + i;
    }
    printf("%d\n", sum);
    return 0;
}
EOF)

Tôi đã phải đưa ra nhận xét. Không có gì sai với câu trả lời - nó khá tốt. Tuy nhiên, để cho thấy rằng bình luận làm cho câu trả lời tuyệt vời, tôi chỉ nâng cao nhận xét.
bballdave025

3

Xin lỗi trước về khả năng đọc của backticks ("` "), nhưng chúng hoạt động trong các shell khác với bash và do đó dễ bị dán hơn. Nếu bạn sử dụng shell chấp nhận nó, định dạng $ (lệnh ...) sẽ dễ đọc hơn (và do đó có thể gỡ lỗi) hơn `lệnh ...` vì vậy hãy thoải mái sửa đổi cho sự tỉnh táo của bạn.

Tôi có một hàm đơn giản trong bashrc của mình, nó sẽ sử dụng awk để tính toán một số mục toán học đơn giản

calc(){
  awk 'BEGIN{print '"$@"' }'
}

Điều này sẽ làm +, -, *, /, ^,%, sqrt, sin, cos, ngoặc đơn .... (và nhiều hơn nữa tùy thuộc vào phiên bản awk của bạn) ... đầu ra, nhưng đây là tất cả những gì tôi thường cần

Đối với câu hỏi cụ thể này, tôi chỉ cần làm điều này cho mỗi dòng:

calc `echo "$@"|tr " " "+"`

vì vậy khối mã để tổng hợp từng dòng sẽ trông giống như thế này:

while read LINE || [ "$LINE" ]; do
  calc `echo "$LINE"|tr " " "+"` #you may want to filter out some lines with a case statement here
done

Đó là nếu bạn muốn chỉ tổng hợp từng dòng một. Tuy nhiên, với tổng số mỗi số trong tệp dữ liệu

VARS=`<datafile`
calc `echo ${VARS// /+}`

btw nếu tôi cần làm gì đó nhanh chóng trên máy tính để bàn, tôi sử dụng cái này:

xcalc() { 
  A=`calc "$@"`
  A=`Xdialog --stdout --inputbox "Simple calculator" 0 0 $A`
  [ $A ] && xcalc $A
}

2
Bạn đang sử dụng loại vỏ cổ nào không hỗ trợ $()?
nyuszika7h
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.