ฉันจะหาผลรวมของจำนวนบรรทัดในไฟล์ได้อย่างไร


24

ฉันมีไฟล์ซึ่งมีลักษณะดังนี้:

1
3
4
1
4
3
1
2

ฉันจะหาผลรวมทั้งหมดได้อย่างไร (เช่น 1 + 3 + 4 + 1 + 4 + 3 + 1 + 2 = 19)


1
สำหรับบริบทฉันนับจำนวนป้ายที่ฉันมีใน Ask Ubuntu จาก Stack Exchange API
ทิม

ด้วยcat badges.json | grep -o '"award_count":[0-9],"rank":"gold"' | grep -o [0-9]
ทิม

แม้ว่าตอนนี้ฉันจะรู้ว่า API มีbadge_countวิธีการ
ทิม

หากคุณกำลังนับตราจาก API ภาษาที่คุณใช้ในการสืบค้น API ไม่สามารถทำได้ (python, javascript)?
Braiam

คำตอบ:


42

bcด้วยความช่วยเหลือเล็กน้อยจากpasteการรับบรรทัดในหนึ่งเดียวด้วย+เป็นตัวคั่น:

paste -sd+ file.txt | bc

หากต้องการใช้เอาต์พุตของgrep(หรือคำสั่งอื่นใด) แทนไฟล์สแตติกให้ส่งgrepSTDOUT ของไปที่ STDIN ของpaste:

grep .... | paste -sd+ | bc

ตัวอย่าง:

% cat file.txt            
1
3
4
1
4
3
1
2

% paste -sd+ file.txt | bc
19

% grep . file.txt | paste -sd+ | bc
19

หากคุณต้องใช้bashคุณสามารถใช้อาร์เรย์เพื่อบันทึกเนื้อหาไฟล์แล้ววนซ้ำองค์ประกอบหรือคุณสามารถอ่านบรรทัดไฟล์ทีละบรรทัดและทำผลรวมสำหรับแต่ละบรรทัดวิธีที่สองจะมีประสิทธิภาพมากขึ้น:

$ time { nums=$(<file.txt); for i in ${nums[@]}; do (( sum+=i )); done; echo $sum ;}
19

real    0m0.002s
user    0m0.000s
sys 0m0.000s

$ time { while read i; do (( sum+=i )); done <file.txt; echo $sum ;}
19

real    0m0.000s
user    0m0.000s
sys 0m0.000s

อืมเยี่ยมมาก ขออภัยที่จะเปลี่ยนคำถาม: ฉันสามารถปรับเปลี่ยนนี้เพื่อยอมรับ grep output (หรือทำให้เป็นหนึ่งบรรทัดได้cat file.txt | bcหรือไม่)
Tim

@Tim ตรวจสอบการแก้ไขของฉัน
heemayl

ทานั่นง่ายมาก!
ทิม

2
วิธี stdin paste -sd+ -ไม่ทำงานสำหรับฉันจนกว่าฉันค้นพบในคำตอบอื่นที่ฉันมีกับการใช้งาน โปรดแก้ไขด้วย
Xerus

19

คุณสามารถใช้ awk ได้เช่นกัน หากต้องการนับจำนวนบรรทัดทั้งหมดในไฟล์* .txtที่มีคำว่า "hello":

grep -ch 'hello' *.txt | awk '{n += $1}; END{print n}'

ในการรวมตัวเลขในไฟล์ให้ทำดังนี้

awk '{n += $1}; END{print n}' file.txt

แต่ถ้าบรรทัดนั้นมีค่า "4" จะไม่นับ 4 มันจะนับ 1
ทิม

ไม่มันจะนับ 4
CrazyApe84

ฉันต้องการจำนวนทั้งหมดในไฟล์ มันทำอย่างนั้นเหรอ?
ทิม

ฉันคิดว่าคุณเปลี่ยนคำถามของคุณเป็นผลลัพธ์ของ grep ฉันกำลังตั้งสมมติฐาน ฉันจะเพิ่มวิธีการรวมค่าในไฟล์
CrazyApe84

2
ใช่. มันเป็นคำตอบเดียวกับ heemayl แต่แทนที่จะใช้วางและ bc ใช้ awk ซึ่งท้ายที่สุดก็ให้ความยืดหยุ่นมากกว่า ถึงกระนั้นคำตอบของเขาก็ดีและเขาเป็นคนแรกดังนั้นเขาจึงสมควรได้รับการโหวตของคุณ!
CrazyApe84

7

ใช้numsumจากแพ็คเกจnum-utils!

(คุณอาจต้องsudo apt-get install num-utils)

คำสั่งnumsumทำตามที่คุณต้องการโดยปริยาย

$ numsum file.txt 
19

อ่านหมายเลขทดสอบทีละบรรทัดจากstdin:

$ printf '
1 
3
4
1
4
3
1
2' | numsum
19

หรืออ่านจากหนึ่งบรรทัด:

$ printf '1 3 4 1 4 3 1 2' | numsum -r
19


สาธารณูปโภคเพิ่มเติม

แพคเกจประกอบด้วยยูทิลิตี้อื่น ๆ สำหรับการประมวลผลหมายเลขที่ควรจะเป็นที่รู้จักมากขึ้น:

numaverage   - find the average of the numbers, or the mode or median
numbound     - find minimum of maximum of all lines
numgrep      - to find numbers matching ranges or sets
numinterval  - roughly like the first derivative
numnormalize - normalize numbers to an interval, like 0-1
numrandom    - random numbers from ranges or sets, eg odd.  
numrange     - similar to seq
numround     - round numbers up, down or to nearest

และคำสั่งเครื่องคิดเลขทั่วไปมากขึ้นnumprocess,
ที่ใช้การแสดงออกจากบรรทัดคำสั่งไปยังหมายเลขบนเส้นที่นำเข้า


1

คุณสามารถใช้awkแอพพลิเคชั่น linux แบบเนทีฟใช้ในการสแกนและประมวลผลไฟล์ด้วยรูปแบบต่อบรรทัด สำหรับคำถามของคุณสิ่งนี้จะสร้างสิ่งที่คุณต้องการ:

awk 'BEGIN { sum=0 } { sum+=$1 } END {print sum }' file.txt

ท่อก็ยอมรับ:

cat file.txt | awk 'BEGIN { sum=0 } { sum+=$1 } END {print sum }'

มีความจำเป็นในการไม่มีBEGIN{}บล็อกดูคำตอบของ CrazyApe84
terdon

มันซ้ำซ้อนกับปัญหานี้ แต่ฉันต้องการรวมไว้เนื่องจากวัตถุประสงค์การสอน
gwarah

แต่มันสอนอะไร มันซ้ำซ้อนกับทุกปัญหาawkไม่ใช่ C คุณไม่จำเป็นต้องตั้งค่าตัวแปรก่อนใช้ ลองawk 'BEGIN{print c+=1}'ดู
terdon

BEGIN {}บล็อกไม่ได้ออกแบบมาเพื่อเริ่มต้นตัวแปร มันมีส่วนร่วมในข้อกำหนดการออกแบบ ดังนั้นในบางปัญหาอาจจำเป็นต้องใช้
gwarah

0

นี่เป็นการใช้bashสคริปต์อย่างง่าย

SUM=0; for line in `cat file.txt`; do SUM=$((SUM + line)); done

นี่คือเรียบง่ายและชุดเครื่องมือน้อยกว่าโซลูชั่นปัจจุบัน
เดช

0

วิธีการแก้ปัญหา Perl:

$ perl -lnae '$c+=$_;END{print $c}' input.txt                                                                            
19

ด้านบนสามารถรวมตัวเลขทั้งหมดในหลายไฟล์:

$ perl -lnae '$c+=$_;END{print $c}' input.txt input2.txt                                                                 
34

สำหรับไฟล์หลายไฟล์ที่กำหนดในบรรทัดคำสั่งที่เราต้องการดูผลรวมของตัวเลขในไฟล์แต่ละไฟล์เราสามารถทำได้:

$ perl -lnae '$c+=$_;if(eof){printf("%d %s\n",$c,$ARGV);$c=0}' input.txt input2.txt                                      
19 input.txt
15 input2.txt


0

วิธีการง่าย ๆ คือการใช้คุณสมบัติในตัวของเชลล์:

SUM=0; while read N; do SUM=$((SUM+N)); done </path/to/file
echo $SUM

นี้จะอ่านไฟล์ของคุณ linewise ผลรวมและพิมพ์ผลลัพธ์

หากคุณต้องการใช้ไปป์และใช้เฉพาะแถวที่ 1 มันจะทำงานดังนี้:

SUM=0
your_command | while read -r LINE; do for N in $LINE; do break; done; SUM=$((SUM+N)); done
echo $SUM

รับองค์ประกอบแรกจะทำเช่นนี้

LIST="foo bar baz"
for OBJ in $LIST; do break; done
echo $OBJ

foo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.