শেল কমান্ড পূর্ণসংখ্যা, প্রতি লাইনে এক?


866

আমি একটি কমান্ড সন্ধান করছি যা গ্রহণের (ইনপুট হিসাবে) একাধিক লাইনের পাঠ্য গ্রহণ করবে, প্রতিটি লাইন একটি একক পূর্ণসংখ্যাযুক্ত এবং এই সংখ্যার যোগফল আউটপুট করবে।

কিছুটা ব্যাকগ্রাউন্ড হিসাবে, আমার একটি লগ ফাইল রয়েছে যা সময় নির্ধারণের পরিমাপ অন্তর্ভুক্ত করে। প্রাসঙ্গিক রেখাগুলি এবং কিছুটা sedপুনরায় ফর্ম্যাট করার জন্য গ্রেপিংয়ের মাধ্যমে আমি সেই ফাইলের সমস্ত সময় তালিকাবদ্ধ করতে পারি। আমি মোট কাজ করতে চাই। আমি এই মধ্যবর্তী আউটপুটটি কোনও কমান্ডের সাথে চূড়ান্ত যোগফলটি করতে পাইপ করতে পারি। আমি সর্বদা exprঅতীতে ব্যবহার করেছি , তবে এটি আরপিএন মোডে না চললে আমি মনে করি না যে এটি এটিকে মোকাবেলা করতে চলেছে (এবং তারপরেও এটি জটিল হবে)।

আমি সংখ্যার যোগফল কীভাবে পেতে পারি?


2
এই খুব একটা প্রশ্ন কিছুক্ষণ আগে নাকি আমি জিজ্ঞাসা অনুরূপ stackoverflow.com/questions/295781/...
অ্যান্ড্রু

5
আমি সত্যই এই প্রশ্নটি পছন্দ করি যে এখানে অনেকগুলি সঠিক সঠিক (বা কমপক্ষে কাজ করা) উত্তর রয়েছে।
ফ্রান্সিসকো কানাডো

এই প্রশ্নটি কোড গল্ফের জন্য একটি সমস্যার মতো অনুভব করে। কোডগলফ.স্ট্যাকেক্সেঞ্জঞ্জ ডটকম :)
গর্ডন বিন

উত্তর:


1320

বিট অব দ্য ডক?

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

দ্রষ্টব্য: অজকের কয়েকটি সংস্করণে কিছু অদ্ভুত আচরণ রয়েছে যদি আপনি 2 ^ 31 (2147483647) এর বেশি কিছু যোগ করতে যাচ্ছেন। আরও পটভূমি জন্য মন্তব্য দেখুন। একটি পরামর্শ printfপরিবর্তে ব্যবহার করা হয় print:

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

7
এই ঘরে অজস্র ভালবাসা আছে! আমি পছন্দ করি যে কীভাবে এই জাতীয় সরল স্ক্রিপ্টটি $ 1 থেকে $ 2 পরিবর্তন করে ডেটার দ্বিতীয় কলাম যুক্ত করতে সংশোধন করা যেতে পারে
পল ডিকসন

2
কোনও ব্যবহারিক সীমা নেই, যেহেতু এটি স্ট্রিম হিসাবে ইনপুটটি প্রক্রিয়া করবে। সুতরাং, যদি এটি এক্স লাইনের কোনও ফাইল পরিচালনা করতে পারে তবে আপনি নিশ্চিত হতে পারেন যে এটি এক্স + 1 হ্যান্ডেল করতে পারে।
পল ডিকসন

4
আমি একবার ছুটির ইউটিলিটি দিয়ে চালানো একটি awk স্ক্রিপ্ট সহ একটি প্রাথমিক মেলিং তালিকা প্রসেসর লিখেছিলাম। ভাল সময়। :)
এলএস

2
সবেমাত্র এটির জন্য এটি ব্যবহার করেছেন: সমস্ত নথির পৃষ্ঠাগুলির স্ক্রিপ্টটি গণনা করুন:ls $@ | xargs -i pdftk {} dump_data | grep NumberOfPages | awk '{s+=$2} END {print s}'
উড়ন্ত ভেড়া

8
সতর্কতা অবলম্বন করুন, এটি 2147483647 (অর্থাত্ 2 ^ 31) এর বেশি সংখ্যার সাথে কাজ করবে না, কারণ অ্যাডাব্লিক 32 বিট স্বাক্ষরিত পূর্ণসংখ্যার উপস্থাপনা ব্যবহার করে। awk '{s+=$1} END {printf "%.0f", s}' mydatafileপরিবর্তে ব্যবহার করুন।
জিয়ানকার্লো স্পোর্টেলি

665

আটকানো সাধারণত একাধিক ফাইলের লাইনগুলিকে একত্রিত করে তবে এটি কোনও ফাইলের স্বতন্ত্র লাইনগুলিকে একক লাইনে রূপান্তর করতেও ব্যবহার করা যেতে পারে। ডিলিমিটার পতাকা আপনাকে বিসিতে একটি এক্স + এক্স টাইপ সমীকরণ পাস করতে দেয়।

paste -s -d+ infile | bc

বিকল্পভাবে, স্টিডিন থেকে পাইপ করার সময়,

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

1
খুব সুন্দর! আমি আরও ভাল করে পার্স করার জন্য আমাকে "+" এর আগে একটি জায়গা রেখে দিতাম, তবে পেস্টের মাধ্যমে কিছু মেমরি নম্বর পাইপ করার জন্য এটি খুব সহজ ছিল এবং তারপরে বিসি।
মাইকেল এইচ।

73
অজানা সমাধানের চেয়ে মনে রাখা এবং টাইপ করা অনেক সহজ। এছাড়াও নোট করুন যে ফাইলটির নাম হিসাবে pasteকোনও ড্যাশ ব্যবহার করতে পারে -- যা আপনাকে কোনও ফাইল তৈরির আগে কোনও আদেশের আউটপুট থেকে পেস্টের স্ট্যান্ডার্ড আউটপুটে নম্বরগুলি পাইপ করতে দেয়:<commands> | paste -sd+ - | bc
জর্জ

19
আমার কাছে 100 মিলিয়ন নম্বর সহ একটি ফাইল রয়েছে। Awk কমান্ডটি 21 সেকেন্ড নেয়; পেস্ট কমান্ডটি 41 সেকেন্ড লাগে। তবুও 'পেস্ট' দেখা ভাল!
অভি

4
@ আবি: আকর্ষণীয়: ডিআই অনুমান করে যে আমার কাছে এসইডি কম্যান্ডটি বের করতে আমার ২০ বছর সময় লাগবে তাই এটি যদি আমার ১০০ মিলিয়ন ও একটি নম্বর চেষ্টা না করে তবেই এটি সমাহিত হয়: ডি
মার্ক কে কোয়ান

6
@ জর্জি আপনি তবে ছেড়ে দিতে পারেন -। (আপনি স্টিডিনের সাথে কোনও ফাইল সংযুক্ত করতে চাইলে এটি কার্যকর )।
অ্যালোস মাহডাল

128

পাইথনের ওয়ান-লাইনার সংস্করণ:

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

সর্বোপরি এক-লাইনের sys.argv [] থাকা ফাইলগুলির জন্য কাজ করে না, কিন্তু যে এক নয় stackoverflow.com/questions/450799/...
JFS

সত্য - লেখক বলেছিলেন যে তিনি অন্য স্ক্রিপ্ট থেকে কমান্ডে পাইপ আউটপুট দিতে যাচ্ছেন এবং আমি এটিকে যতটা সম্ভব সংক্ষিপ্ত করার চেষ্টা করছি :)
ডিএফ।

39
সংক্ষিপ্ত সংস্করণটি হবেpython -c"import sys; print(sum(map(int, sys.stdin)))"
jfs

4
আমি এই উত্তরটি পড়ার স্বাচ্ছন্দ্য এবং নমনীয়তার জন্য পছন্দ করি। ডিরেক্টরি সংগ্রহের জন্য আমার 10Mb এর চেয়ে কম ফাইলের গড় আকার দরকার ছিল এবং এটিতে এটি সংশোধন করা হয়েছিল: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))"
পল হিপ

1
যদি আপনার কিছু পাঠ্য মিশ্রিত হয় তবে আপনি অ সংখ্যাগুলিও ফিল্টার করতে পারেন:import sys; print(sum(int(''.join(c for c in l if c.isdigit())) for l in sys.stdin))
গ্রানিতোসরাস

91

আমি সাধারণভাবে অনুমোদিত সমাধানটিতে একটি বড় সতর্কতা রাখব:

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

কারণ এই ফর্মটিতে অর্ক একটি 32 বিট স্বাক্ষরিত পূর্ণসংখ্যার উপস্থাপনা ব্যবহার করে: এটি 2147483647 (অর্থাত্ 2 ^ 31) অতিক্রমকারী অঙ্কের জন্য উপচে পড়বে।

আরও সাধারণ উত্তর (সংখ্যার যোগফলের জন্য) হ'ল:

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

প্রিন্টফ () এখানে কেন সহায়তা করে? ইন্টের ওভারফ্লো এর আগে ঘটবে কারণ সমষ্টি কোডটি একই।
রবার্ট ক্লেমে

9
কারণ সমস্যাটি আসলে "মুদ্রণ" ফাংশনে। আওক bit৪ বিট পূর্ণসংখ্যার ব্যবহার করে তবে কোনও কারণে মুদ্রণটি তাদের 32 বিটে ডনস্কল করে।
জিয়ানকার্লো স্পোর্টেলি

4
মুদ্রণ বাগটি কমপক্ষে appears.০.১ ও ব্যাশ ৪.৩.১১ এর জন্য ঠিক হয়ে গেছে বলে মনে হচ্ছে, যদি না আমি ভুল করে থাকি: echo -e "2147483647 \n 100" |awk '{s+=$1}END{print s}'শো2147483747
Xen2050

4
ফ্লোটগুলি ব্যবহার করা কেবল একটি নতুন সমস্যার পরিচয় দেয়: echo 999999999999999999 | awk '{s+=$1} END {printf "%.0f\n", s}'উত্পাদন করে1000000000000000000
প্যাট্রিক 18

1
64bit সিস্টেমে "% ld" ব্যবহার না করে 32fbit এ প্রিন্টফ ট্রাঙ্কেট না রাখার কাজ করা উচিত? @ পেট্রিক যেমন উল্লেখ করেছেন, ভাসমানগুলি এখানে দুর্দান্ত ধারণা নয়।
yerforkferchips

78

সরল বাশ:

$ 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


@ রজ্যাক, numসংজ্ঞায়িত কোথায় ? আমি বিশ্বাস করি যে এটি কোনওভাবেই < numbers.txtপ্রকাশের সাথে সংযুক্ত , তবে কীভাবে তা পরিষ্কার নয়।
আটকোল্ড

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

দ্রষ্টব্য যে বিয়োগ চিহ্ন সহ উপসর্গ করা নেতিবাচক সংখ্যাগুলির জন্য অনুবাদ করা উচিত dc, কারণ এটি এর জন্য _উপসর্গের পরিবর্তে -উপসর্গ ব্যবহার করে। উদাহরণস্বরূপ, মাধ্যমে tr '-' '_' | dc -f- -e '...'

সম্পাদনা: যেহেতু এই উত্তরটি "অস্পষ্টতার জন্য" এত বেশি ভোট পেয়েছে, তাই এখানে একটি বিশদ ব্যাখ্যা রয়েছে:

এক্সপ্রেশন [+z1<r]srz1<rp নিম্নলিখিতটি করে :

[   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

সিউডো কোড হিসাবে:

  1. "অ্যাড_টপ_ফ_স্ট্যাক" হিসাবে এটি নির্ধারণ করুন:
    1. স্ট্যাকের বাইরে দুটি শীর্ষ মান মুছে ফেলুন এবং ফলাফলটি আবার যুক্ত করুন
    2. স্ট্যাকের যদি দুটি বা ততোধিক মান থাকে তবে "add_top_of_stack" পুনরাবৃত্তভাবে চালান
  2. স্ট্যাকের যদি দুটি বা ততোধিক মান থাকে তবে "add_top_of_stack" চালান
  3. ফলটি মুদ্রণ করুন, এখন স্ট্যাকের মধ্যে কেবলমাত্র আইটেমটি রয়েছে

এর সরলতা এবং শক্তি সত্যিই বুঝতে dc, এখানে একটি কার্যকরী পাইথন স্ক্রিপ্ট রয়েছে যা dcউপরের কমান্ডের পাইথন সংস্করণ থেকে কিছু কমান্ড প্রয়োগ করে এবং সম্পাদন করে:

### 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
ডিসি ব্যবহারের জন্য পছন্দসই সরঞ্জাম। তবে আমি এটি একটু কম স্ট্যাক অপ্স দিয়ে করব। অধিকৃত যে সব লাইন সত্যিই একটি সংখ্যা উপস্থিত: (echo "0"; sed 's/$/ +/' inp; echo 'pq')|dc
ইকরাব

5
অনলাইন অ্যালগরিদম: dc -e '0 0 [+?z1<m]dsmxp'। সুতরাং আমরা প্রক্রিয়া করার আগে স্ট্যাকের সমস্ত সংখ্যা সংরক্ষণ করি না তবে সেগুলি একে একে পড়ি এবং প্রসেস করি (আরও সুনির্দিষ্টভাবে বলতে গেলে, প্রতিটি লাইনে লাইন, যেহেতু এক লাইনে বেশ কয়েকটি সংখ্যা থাকতে পারে)। নোট করুন যে খালি লাইনটি একটি ইনপুট ক্রমটি শেষ করতে পারে।
রুভিম

@ কিক্রাবে এটি দুর্দান্ত। এটি আরও একটি চরিত্র দ্বারা আসলে সংক্ষিপ্ত করা sedযেতে পারে: dc আর্গুমেন্ট এবং অপারেটরদের মধ্যে ফাঁকা স্থানগুলির কোনও যত্ন নেই বলে প্রতিস্থাপনের স্থানটি সরানো যেতে পারে । (echo "0"; sed 's/$/+/' inputFile; echo 'pq')|dc
হোয়াইট হটলভটাইজার

58

সঙ্গে jq :

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

7
আমি এটি পছন্দ করি কারণ আমার ধারণা এটি এত স্পষ্ট এবং সংক্ষিপ্ত যে আমি সম্ভবত এটি মনে করতে সক্ষম হতে পারি।
Alfe

46

খাঁটি এবং সংক্ষিপ্ত বাশ

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

9
এটি সেরা সমাধান কারণ আপনি যদি প্রথম লাইনটি প্রতিস্থাপন করেন তবে এটি কোনও সাবপ্রসেস তৈরি করে না f=$(<numbers.txt)
loentar

1
স্টিডিন থেকে ইনপুট পাওয়ার কোনও উপায়? একটি পাইপ থেকে পছন্দ?
njzk2

@ njzk2 আপনি যদি f=$(cat); echo $(( ${f//$'\n'/+} ))কোনও স্ক্রিপ্ট রেখে দেন তবে আপনি সেই স্ক্রিপ্টে যে কোনও কিছু পাইপ করতে পারেন বা ইন্টারেক্টিভ স্টিডিন ইনপুট (কন্ট্রোল-ডি দিয়ে সমাপ্ত) এর জন্য যুক্তি ছাড়াই এটিকে আবেদন করতে পারেন।
mklement0

5
@ লেন্টার <numbers.txtএটি একটি উন্নতি, তবে সামগ্রিকভাবে, এই সমাধানটি কেবলমাত্র ছোট ইনপুট ফাইলগুলির জন্য দক্ষ; উদাহরণস্বরূপ, এক হাজার ইনপুট লাইনের একটি ফাইল সহ গ্রহণযোগ্য awkসমাধানটি আমার মেশিনে প্রায় 20 গুণ বেশি দ্রুত - এবং কম স্মৃতিও গ্রহন করে, কারণ ফাইলটি একবারে একসাথে পড়া হয় না।
mklement0

2
আমি যখন এইটি পৌঁছেছিলাম তখন প্রায় আশা হারিয়েছিলাম had খাঁটি বাশ!
ওমর আক্তার

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

4
এবং আমি তাদের আবার যুক্ত করেছি: "-l" নিশ্চিত করে যে আউটপুটটি শেল `` ব্যাকটিক্স হিসাবে এলএফ-টার্মিনেটেড এবং বেশিরভাগ প্রোগ্রাম প্রত্যাশা করে এবং "<" ইঙ্গিত করে যে এই আদেশটি পাইপলাইনে ব্যবহার করা যেতে পারে।
j_random_hacker

তুমি ঠিক. অজুহাত হিসাবে: পার্ল ওয়ান-লাইনারের প্রতিটি চরিত্রের জন্য আমার একটি মানসিক কাজ প্রয়োজন, তাই আমি যতটা সম্ভব চরিত্রগুলি ছাঁটাই করতে পছন্দ করি। এই ক্ষেত্রে অভ্যাসটি ক্ষতিকারক ছিল।
jfs

2
র‌্যামে সমস্ত কিছু লোড না করে এমন কয়েকটি সমাধানগুলির মধ্যে একটি।
এরিক অ্যারোনস্টি

28

আমার পনেরটি সেন্ট:

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

উদাহরণ:

$ 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

আমার ইনপুটটিতে ফাঁকা লাইন থাকতে পারে তাই আপনি এখানে যা পোস্ট করেছেন তা ব্যবহার করেছি এ grep -v '^$'। ধন্যবাদ!
জেমস ওরাভেক 16

কি দারুন!! আপনার উত্তর আশ্চর্যজনক! হেঁটে যাওয়া সবার থেকে আমার ব্যক্তিগত প্রিয়
thahgr

পাইপলাইনের জন্য এটি এবং +1 পছন্দ করুন। আমার জন্য খুব সহজ এবং সহজ সমাধান
জেলিন লুও

24

আমি বিদ্যমান উত্তরগুলির উপর একটি দ্রুত মানদণ্ড করেছি

  • কেবলমাত্র স্ট্যান্ডার্ড সরঞ্জামগুলি ব্যবহার করুন (যেমন পণ্যগুলির জন্য দুঃখিত luaবা rocket),
  • সত্যিকারের এক-রেখার,
  • বিপুল পরিমাণ সংখ্যক (100 মিলিয়ন) যোগ করতে সক্ষম, এবং
  • দ্রুত (আমি এক মিনিটের চেয়ে বেশি সময় নিয়ে এগুলিকে উপেক্ষা করেছি)।

আমি সর্বদা 1 থেকে 100 মিলিয়ন সংখ্যার যোগ করেছিলাম যা বেশ কয়েকটি সমাধানের জন্য আমার মেশিনে এক মিনিটেরও কম সময়ে কার্যকর ছিল।

ফলাফল এখানে:

পাইথন

:; 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

আটকান এবং বিসি

এটি আমার মেশিনে স্মৃতিশক্তি হারিয়েছে। এটি ইনপুটটির অর্ধেক আকারের জন্য কাজ করেছে (50 মিলিয়ন সংখ্যা):

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

সুতরাং আমার ধারণা 100 মিলিয়ন সংখ্যার জন্য এটি 35 ডলার লাগবে।

পার্ল

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

চুনি

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

সি

কেবল তুলনার স্বার্থে আমি সি সংস্করণটি সংকলিত করেছি এবং এটিও পরীক্ষা করেছি, কেবলমাত্র সরঞ্জাম-ভিত্তিক সমাধানগুলি কত ধীর গতিযুক্ত তা ধারণা পেতে।

#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

উপসংহার

সি অবশ্যই 8s এর সাথে দ্রুততম, তবে পাইপির সমাধানটি প্রায় 30% থেকে 11s এর খুব সামান্য ওভারহেড যুক্ত করে । তবে, সত্যি কথা বলতে গেলে পাইপি ঠিক স্ট্যান্ডার্ড নয়। বেশিরভাগ লোকেরা কেবল সিপিথন ইনস্টল করে রেখেছেন যা উল্লেখযোগ্যভাবে ধীর (22 সে), জনপ্রিয় ওউ সমাধান হিসাবে ঠিক তত দ্রুত।

মানক সরঞ্জামগুলির উপর ভিত্তি করে দ্রুততম সমাধান হ'ল পার্ল (15 এস)।


2
paste+ + bcপদ্ধতির ঠিক কি আমি সমষ্টি হেক্স মান খুঁজছেন ছিল ছিল, ধন্যবাদ!
টমিস্লাভ নাকিক-আলফায়ারভিক

1
কেবল মজাদার জন্য, মরিচায়: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); }
জোসলিন

দুর্দান্ত উত্তর নিটপিক নয়, তবে আপনি যদি সেই দীর্ঘকালীন ফলাফলগুলি অন্তর্ভুক্ত করার সিদ্ধান্ত নেন তবে উত্তরটি আরও দুর্দান্ত হবে!
স্টিভেন লু

@ স্টিভেনলু আমি অনুভব করেছি উত্তরটি কেবল দীর্ঘ হবে এবং এইভাবে কম ভয়ঙ্কর হবে (আপনার শব্দ ব্যবহার করার জন্য)। তবে আমি বুঝতে পারি যে এই অনুভূতিটি সবার ভাগ করে নেওয়া উচিত নয় :)
Alfe

পরবর্তী: নাম্বা + সমান্তরালতা
15-22


17

BASH সমাধান, যদি আপনি এটি একটি আদেশ করতে চান (যেমন আপনার যদি প্রায়শই এটি করা প্রয়োজন):

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

তারপরে ব্যবহার:

addnums < /tmp/nums

14

আমি মনে করি AWK হ'ল আপনি যা খুঁজছেন:

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

আপনি এই কমান্ডটি হয় আদর্শ ইনপুটটির মাধ্যমে সংখ্যা তালিকা পাস করে অথবা পরামিতি হিসাবে সংখ্যাযুক্ত ফাইলটি পাস করার মাধ্যমে ব্যবহার করতে পারেন।


2
: এটি একটি DUP এর stackoverflow.com/questions/450799/...
JFS

11

নীচে বাশ কাজ করে:

I=0

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

echo $I

1
ফাইলগুলি যখন স্বেচ্ছায় বড় হতে পারে তখন কমান্ড প্রসারণটি সতর্কতার সাথে ব্যবহার করা উচিত। 10MB এর সংখ্যা .txt সহ, cat numbers.txtপদক্ষেপটি সমস্যাযুক্ত হবে।
গিয়াকোমো

1
আসলে, তবে (যদি এখানে পাওয়া ভাল সমাধানগুলির জন্য না হয়) আমি আসলে এটির সমস্যাটি না হওয়া পর্যন্ত আমি এটি ব্যবহার করব।
ফ্রান্সিসকো কানাডো

11

আপনি নাম-ব্যবহারগুলি ব্যবহার করতে পারেন, যদিও এটি আপনার প্রয়োজনের জন্য ওভারকিল হতে পারে। এটি শেলের মধ্যে সংখ্যাগুলি হেরফের করার জন্য প্রোগ্রামগুলির একটি সেট এবং এগুলি যুক্ত করে অবশ্যই বেশ কয়েকটি নিফটি কাজ করতে পারে। এটি কিছুটা পুরানো, তবে তারা এখনও কাজ করে এবং আপনার আরও কিছু করার প্রয়োজন হলে দরকারী হতে পারে।

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


উদাহরণ: numsum numbers.txt
এগ্রি

9

আমি বুঝতে পারি এটি একটি পুরানো প্রশ্ন, তবে আমি এই সমাধানটি ভাগ করে নেওয়ার পক্ষে এটি পছন্দ করি।

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

যদি আগ্রহ থাকে তবে আমি কীভাবে এটি কাজ করে তা ব্যাখ্যা করব।


10
দয়া করে না। আমরা ভান করতে চাই যে -n এবং -p
হ'ল চমত্কার

2
হ্যাঁ, দয়া করে ব্যাখ্যা করুন :) (আমি পার্ল টাইপিয়া লোক নই))
জেনস

1
"পার্ল-এমও = Deparse -lpe '$ c + = $ _} {= _ = $ সি'" চালানোর চেষ্টা করুন এবং আউটপুট দিকে তাকান, মূলত -l নিউলাইন এবং উভয় ইনপুট এবং আউটপুট বিভাজক ব্যবহার করে এবং -p প্রতিটি লাইন মুদ্রণ করে। তবে '-p' করার জন্য, পার্ল প্রথমে কিছু বয়লার প্লেট যুক্ত করে (যা -MO = Deparse) আপনাকে প্রদর্শন করবে তবে তারপরে এটি কেবল বিকল্প এবং সংকলন করবে। আপনি এভাবে '} {' অংশের সাহায্যে একটি অতিরিক্ত ব্লক sertedোকাতে এবং এটিকে প্রতিটি লাইনে মুদ্রণ না করে চালিত করতে পারেন, তবে একেবারে শেষে মুদ্রণ করতে পারেন।
নিম



6

বিকল্প বিশুদ্ধ পার্ল, মোটামুটি পাঠযোগ্য, কোনও প্যাকেজ বা বিকল্পের প্রয়োজন নেই:

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

বা একটি সামান্য বিট সংক্ষিপ্ত: পার্ল-e 'মানচিত্র {$ x + = $ _} <>; $ x 'infile.txt মুদ্রণ করুন
আভি

10 মিলিয়ন সংখ্যার বড় ইনপুটটির জন্য মেমোরিটির প্রায় 2 গিগাবাইট প্রয়োজন
অমিত নাইডু

6

রুবি প্রেমীদের জন্য

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

5

এটি জমা দেওয়া এড়ানো যায় না:

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

এটি এখানে পাওয়া যায়:
স্বেচ্ছাসেবক নির্ভুলতার সংখ্যার তালিকা যোগ করতে সর্বাধিক মার্জিত ইউনিক্স শেল ওয়ান-লাইনার?

অজস্র, বিসি এবং বন্ধুদের চেয়ে এখানে এর বিশেষ সুবিধা রয়েছে:

  • এটি বাফারিংয়ের উপর নির্ভর করে না এবং এটি সত্যিই বড় ইনপুটগুলির সাথে শ্বাসরোধ করে না
  • এটি কোনও নির্দিষ্ট নির্ভুলতা-বা সীমাবদ্ধতার জন্য পূর্ণসংখ্যার আকার বোঝায়
  • বিভিন্ন কোডের প্রয়োজন নেই, যদি ভাসমান পয়েন্ট সংখ্যা যুক্ত করার প্রয়োজন হয়

দয়া করে উত্তরে প্রশ্নের সাথে সম্পর্কিত কোডটি অন্তর্ভুক্ত করুন এবং কোনও লিঙ্কটি উল্লেখ করবেন না
Ibo


4

ব্যবহার গনুহ datamash util :

seq 10 | datamash sum 1

আউটপুট:

55

যদি ইনপুট ডেটাগুলি অনিয়মিত হয় তবে অদ্ভুত জায়গাগুলিতে ফাঁকা স্থান এবং ট্যাবগুলি সহ, এটি বিভ্রান্ত হতে পারে datamash, তবে হয় -Wসুইচটি ব্যবহার করুন :

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

... বা trসাদা স্থান পরিষ্কার করার জন্য ব্যবহার করুন :

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

3

আপনি যদি স্বাচ্ছন্দ্য বোধ করেন তবে অজগরটিতে এটি করতে পারেন:

পরীক্ষা করা হয়নি, কেবল টাইপ করা হয়েছে:

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

সেবাস্তিয়ান একটি একটি লাইন স্ক্রিপ্ট নির্দেশ করেছেন:

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

পাইথন-সি "ফাইলিনপুট আমদানি ইনপুট থেকে; মুদ্রণ যোগ (মানচিত্র (ইনট, ইনপুট ()))"
নাম্বারস.টিএক্সটি

2
বিড়ালটিকে অতিরিক্ত ব্যবহার করা হয়েছে, ফাইল থেকে স্টিডিন পুনঃনির্দেশ করুন: পাইথন-সি "..." <
গিয়াকোমো

2
@rjack: catস্ক্রিপ্টটি স্ট্ডিনের জন্য এবং আরজিভিতে ফাইলগুলির জন্য [] যেমন while(<>)পার্লের মতো ) উভয়ই কাজ করে তা প্রমাণ করতে ব্যবহৃত হয় । যদি আপনার ইনপুট কোনও ফাইলে থাকে তবে '<' অপ্রয়োজনীয়।
jfs

2
তবে < numbers.txtদেখায় যে এটি স্টিডিনে যেমন কাজ করে তেমনি cat numbers.txt |করে। এবং এটি খারাপ অভ্যাস শেখায় না।
শাওনিং চিয়ামিভ

3
$ বিড়াল n
2
4
2
7
8
9
$ perl -MList::Util -le 'print List::Util::sum(<>)' < n
32

অথবা, আপনি কমান্ড লাইনে নম্বর টাইপ করতে পারেন:

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

যাইহোক, এটি ফাইলটি স্লাপ করে তাই বড় ফাইলগুলিতে ব্যবহার করা ভাল ধারণা নয়। দেখুন j_random_hacker এর উত্তর যা slurping এড়াতে।


3

নিম্নলিখিতগুলিতে কাজ করা উচিত (ধরে নিলে আপনার সংখ্যাটি প্রতিটি লাইনের দ্বিতীয় ক্ষেত্র)।

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

2
আপনার সত্যিকারের {যোগ = 0} অংশের প্রয়োজন নেই
আপিল_ কি 1

3

র‌্যাকেটে ওয়ান-লাইনার:

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

3

সি (সরলীকৃত নয়)

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)

আমি মন্তব্য upvote ছিল। উত্তরের সাথে কোনও ভুল নেই - এটি বেশ ভাল। যাইহোক, মন্তব্যটি উত্তরটিকে দুর্দান্ত করে তোলে তা দেখানোর জন্য, আমি কেবল মন্তব্যটি উপস্থাপন করছি।
bবলldave025

3

ব্যাকটিক্স ("` ") এর পাঠযোগ্যতার জন্য অগ্রিম ক্ষমাপ্রার্থনা, তবে এগুলি ব্যাশ ব্যতীত অন্য শেলগুলিতে কাজ করে এবং এগুলি আরও পেস্টযোগ্য হয়। আপনি যদি একটি শেল ব্যবহার করেন যা এটি গ্রহণ করে, `(কমান্ড ...) ফর্ম্যাটটি` কমান্ড ... than এর চেয়ে অনেক বেশি পঠনযোগ্য (এবং এভাবে ডিবাজযোগ্য) তাই আপনার বিচক্ষণতার জন্য সংশোধন করতে দ্বিধা বোধ করবেন না।

আমার বাশারসিটিতে আমার একটি সাধারণ ফাংশন রয়েছে যা বেশ কয়েকটি সাধারণ গণিত আইটেম গণনা করার জন্য awk ব্যবহার করবে

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

এটি করবে +, -, *, /, ^% আউটপুট, তবে এগুলি আমার সাধারণত প্রয়োজন

এই নির্দিষ্ট প্রশ্নের জন্য, আমি কেবল প্রতিটি লাইনের জন্য এটি করব:

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

সুতরাং প্রতিটি লাইনের যোগফলের জন্য কোড ব্লকটি এরকম কিছু দেখায়:

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

আপনি যদি কেবল লাইনে তাদের লাইন যোগ করতে চেয়েছিলেন তবে তা। তবে মোট জন্য ডেটা ফাইলের প্রতিটি সংখ্যার জন্য

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

বিটিডাব্লু যদি আমাকে ডেস্কটপে দ্রুত কিছু করার প্রয়োজন হয় তবে আমি এটি ব্যবহার করি:

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

2
আপনি কোন ধরণের প্রাচীন শেল ব্যবহার করছেন যা সমর্থন করে না $()?
nyuszika7h
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.