मैं किसी फ़ाइल में सभी संख्याओं को कैसे जोड़ सकता हूँ?


16

प्रत्येक पंक्ति में एक कॉलम में टेक्स्ट और नंबर होते हैं। मुझे प्रत्येक पंक्ति में संख्याओं के योग की गणना करने की आवश्यकता है। मैं उसे कैसे कर सकता हूँ? धन्यवाद

example.log में शामिल हैं:

time=31sec
time=192sec
time=18sec
time=543sec

उत्तर 784 होना चाहिए


मैंने यह तरीका आज़माया '{sum + = $ 1}; END {प्रिंट योग} 'example.log लेकिन यह केवल पंक्ति में संख्याओं के लिए है
जैक

2
स्टैक ओवरफ्लो में लगभग एक ही सवाल है : मैं किसी फाइल में सभी नंबरों को कैसे जोड़ सकता हूं? । शायद क्रॉस-साइट डुप्लिकेट करने का समय है?
फेडोरक्वी

जवाबों:


18

यदि आपका grepसमर्थन -oविकल्प है, तो आप कोशिश कर सकते हैं:

$ grep -o '[[:digit:]]*' file | paste -sd+ - | bc
784

POSIXly:

$ printf %d\\n "$(( $(tr -cs 0-9 '[\n*]' <file | paste -sd+ -) ))"
784

16

जीएनयू के नए संस्करण (4.x) के साथ awk:

awk 'BEGIN {FPAT="[0-9]+"}{s+=$1}END{print s}'

अन्य awkप्रयासों के साथ :

awk -F '[a-z=]*' '{s+=$2}END{print s}'

4
आपको उस s+0मामले में आवश्यकता है जहां sखाली है, यह 0खाली के बजाय प्रिंट करेगा ।
cuonglm

मुझे वह समझाने दो। - सिर्फ एक मामला है जहां sखाली हो सकता है; यदि इनपुट डेटा में कोई रेखाएँ नहीं हैं (अर्थात यदि कोई इनपुट नहीं है )। उस स्थिति में दो व्यवहार संभव हैं; 1) कोई इनपुट => कोई आउटपुट नहीं, या 2) हमेशा कुछ आउटपुट करते हैं, यदि केवल 0. आवेदन के संदर्भ के आधार पर दोनों समझदार विकल्प हैं। +0विकल्प 2 संबोधित कर रहा है)। विकल्प 1 को संबोधित करने के लिए) आपको लिखना होगा END {if(s) print s}। - इसलिए यह प्रश्न द्वारा निर्दिष्ट किए जाने तक किसी भी विकल्प (बिना डेटा के इस कोने के मामले) के लिए कोई मतलब नहीं है।
जैनिस

10
awk -F= '{sum+=$2};END{print sum}'

2
हम लंबे फॉर्म के उत्तर पसंद करते हैं। क्या आप इस बारे में विस्तार से बता सकते हैं कि यह कैसे काम करता है?
SLM

2
@ एसएलएम, वह उत्तर यहां के अन्य उत्तरों की तुलना में कोई अधिक या कम क्रिया नहीं है और स्वयं व्याख्यात्मक है। इसमें इनपुट के साथ काम करने का भी फायदा है जैसेtime=1.4e5sec
स्टीफन चेजलस

@ StéphaneChazelas - सहमत हैं, लेकिन यह एक नया उपयोगकर्ता है और हम उपयोगकर्ताओं को सिंगल लाइन से अधिक उत्तर प्रदान करने के लिए प्रोत्साहित करते हैं। यह कैसे काम करता है यह समझाने के लिए पाठ का एक सा यह सिर्फ कोड की तुलना में एक बहुत मजबूत जवाब होगा।
SLM

4
@ एसएलएम, यह एक नया उपयोगकर्ता है जिसके पास सबसे अच्छा जवाब है (एक तकनीकी बिंदु से) और उसे दो डाउनवोट और एक नकारात्मक टिप्पणी मिलती है। बहुत गर्मजोशी से स्वागत नहीं।
स्टीफन चेज़लस

1
@TomFenech, awk के लिए POSIX सिंटैक्स के लिए आवश्यक है कि उन पैटर्न / एक्शन आइटम को ""; या "न्यूलाइन", इसलिए आपको अजीब कार्यान्वयन मिल सकते हैं जहां यह इसके बिना विफल हो जाता है ";"।
स्टीफन चेज़लस


6
sed 's/=/ /' file | awk '{ sum+=$2 } END { print sum}'

बहुत बढ़िया जवाब, लेकिन इसके लिए कोई ज़रूरत नहीं है sed:awk --field-separator = '{ sum+=$2 } END { print sum}' data.dat
user1717828

@ user1717828: अगर आप (कम, और अधिक संगत!) का उपयोग करना चाहिए -F'='बजाय--field-separator =
ओलिवर Dulac

@OlivierDulac, अजीब, मेरा man awkएकमात्र देता है -F fsऔर--field-separator fs
user1717828

@ user1717828: -F'='या आपके मामले में (= "=" -F '='करने के 2 तरीके हैं -F fs)। मैंने यह सुनिश्चित करने के लिए एकल जोड़े कि एफएस को ठीक से देखा और व्याख्या की जा रही है, न कि शेल (उपयोगी अगर एफएस 'है?' उदाहरण के लिए)
ओलिवियर ड्यूलाक

4

आप यह कोशिश कर सकते हैं:

awk -F"[^0-9]+" '{ sum += $2 } END { print sum+0; }' file

4

सभी ने कमाल का पोस्ट किया है awk जवाब , जो मुझे बहुत पसंद हैं।

एक बदलाव की जगह @cuonglm के grepसाथ sed:

sed 's/[^0-9]//g' example.log | paste -sd'+' - | bc
  1. sedसंख्याओं के अलावा सब कुछ स्ट्रिप्स।
  2. paste -sd+ -आदेश सभी लाइनों एक साथ जुड़ एक पंक्ति के रूप में
  3. bcअभिव्यक्ति का मूल्यांकन करता है

3

आपको एक कैलकुलेटर का उपयोग करना चाहिए।

{ 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संकलक था - और अभी भी कई प्रणालियों के लिए है।


मेरे माप के अनुसार नहीं : यह निर्भर करता है कि सूत्र बनाने के लिए आपको कितना काम करना है
ग्लेन जैकमैन

@glennjackman - आपके माप में वह सम्‍मिलित नहीं है dcजैसा कि मैं बता सकता हूँ। तुम्हारी किस बारे में बोलने की इच्छा थी?
15

वैसे, जब पुराने क्रू की तुलना नए क्रू से की जाती है - जैसे कि जब आप perlमानक यूनिक्स टूलसेट को बेंचमार्क करते हैं - तो यह वास्तव में बहुत मायने नहीं रखता है यदि आप जीएनयू टूलकिन पर संकलित जीएनयू टूल का उपयोग करते हैं। ब्लोट को नकारात्मक रूप से पर्ल के प्रदर्शन को प्रभावित कर सकते हैं सब के सब है भी में सभी उन जीएनयू संकलित जीएनयू utils के। दुखद लेकिन सत्य। आपको अंतर का सही आंकलन करने के लिए एक वास्तविक, सरल और सरल टूलसेट की आवश्यकता होती है। मिसाल के तौर पर मसल लिबास के खिलाफ एक हिरलूम-टूलचैस्ट सेट स्टैटिकली जुड़ा हुआ है - इस तरह से आप वन-टूल / वन-जॉब प्रतिमान बनाम वन-टू-रूल-टू-रूल-उन-सभी को बेंच सकते हैं।
mikeserv

3

अजगर 3 के माध्यम से,

import re
with open(file) as f:
    m = f.read()
    l = re.findall(r'\d+', m)
    print(sum(map(int, l)))

re.findallस्ट्रिंग्स की एक सूची देता है, यह काम करने वाला नहीं है
इरुवर

@ 1_CR हां, मैं यह भूल गया हूं। अब यह जांच करें।
अविनाश राज

शायद sum(int(e) for e in l)अधिक पाइथोनिक है।
cuonglm

3

शुद्ध बैश समाधान (बैश 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

1
हो सकता है कि यह भी:PS4='$((x+=${time%s*}))' time=0 x=0 sh -x <infile
mikeserv
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.