আমার কাছে 2 মিলিয়ন লাইনযুক্ত একটি পাঠ্য ফাইল রয়েছে। প্রতিটি লাইনের ইতিবাচক পূর্ণসংখ্যা থাকে। আমি ফ্রিকোয়েন্সি টেবিল ধরণের জিনিস গঠনের চেষ্টা করছি।
ইনপুট ফাইল:
3
4
5
8
আউটপুট হওয়া উচিত:
3
7
12
20
কিভাবে আমি এই কাজ সম্পর্কে যান?
আমার কাছে 2 মিলিয়ন লাইনযুক্ত একটি পাঠ্য ফাইল রয়েছে। প্রতিটি লাইনের ইতিবাচক পূর্ণসংখ্যা থাকে। আমি ফ্রিকোয়েন্সি টেবিল ধরণের জিনিস গঠনের চেষ্টা করছি।
ইনপুট ফাইল:
3
4
5
8
আউটপুট হওয়া উচিত:
3
7
12
20
কিভাবে আমি এই কাজ সম্পর্কে যান?
উত্তর:
সাথে awk
:
awk '{total += $0; $0 = total}1'
$0
বর্তমান লাইন সুতরাং, প্রতিটি লাইনের জন্য, আমি এটিকে যুক্ত করব total
, নতুনটিতে লাইনটি সেট করবো total
, এবং তারপরে 1
হ'ল একটি বিশ্রী শর্টকাট - এটি প্রতিটি সত্য শর্তের জন্য বর্তমান লাইনটি মুদ্রণ করে এবং 1
শর্ত হিসাবে সত্য হিসাবে মূল্যায়ন করে।
print
কি ব্যবহার করা যায়?
print total}
পরিবর্তে$0 = total}1
{print(total += $0)}
একটি অজগর লিপি:
#!/usr/bin/env python3
import sys
f = sys.argv[1]; out = sys.argv[2]
n = 0
with open(out, "wt") as wr:
with open(f) as read:
for l in read:
n = n + int(l); wr.write(str(n)+"\n")
add_last.py
উত্স ফাইল এবং লক্ষ্যবস্তু আউটপুট ফাইলটিকে আর্গুমেন্ট হিসাবে এটি চালান:
python3 /path/to/add_last.py <input_file> <output_file>
কোডটি বরং পাঠযোগ্য, তবে বিস্তারিতভাবে:
ফলাফল লেখার জন্য আউটপুট ফাইল খুলুন
with open(out, "wt") as wr:
প্রতি লাইনে পড়ার জন্য ইনপুট ফাইলটি খুলুন
with open(f) as read:
for l in read:
মোটে নতুন লাইনের মান যুক্ত করে লাইনগুলি পড়ুন:
n = n + int(l)
ফলাফল আউটপুট ফাইলে লিখুন:
wr.write(str(n)+"\n")
শুধুই মজার জন্য
$ sed 'a+p' file | dc -e0 -
3
7
12
20
এটি ইনপুটটির প্রতিটি লাইনে একটি পেপেন্ডিংয়ের মাধ্যমে কাজ করে +p
এবং তারপরে ফলাফলটি dc
ক্যালকুলেটরে পাস করে
+ Pops two values off the stack, adds them, and pushes the result.
The precision of the result is determined only by the values of
the arguments, and is enough to be exact.
তারপর
p Prints the value on the top of the stack, without altering the
stack. A newline is printed after the value.
-e0
যুক্তি push কর্মের 0
সম্মুখের dc
স্ট্যাক সমষ্টি আরম্ভ করতে।
real 0m4.234s
স্ট্যান্ডার্ড ইনপুটটিতে প্রতিটি লাইনে দেওয়া পূর্ণসংখ্যার আংশিক পরিমাণ প্রিন্ট করতে:
#!/usr/bin/env python3
import sys
partial_sum = 0
for n in map(int, sys.stdin):
partial_sum += n
print(partial_sum)
যদি কোনও কারণে কমান্ডটি খুব ধীর হয়; আপনি সি প্রোগ্রাম ব্যবহার করতে পারেন:
#include <stdint.h>
#include <ctype.h>
#include <stdio.h>
int main(void)
{
uintmax_t cumsum = 0, n = 0;
for (int c = EOF; (c = getchar()) != EOF; ) {
if (isdigit(c))
n = n * 10 + (c - '0');
else if (n) { // complete number
cumsum += n;
printf("%ju\n", cumsum);
n = 0;
}
}
if (n)
printf("%ju\n", cumsum + n);
return feof(stdin) ? 0 : 1;
}
এটি তৈরি এবং চালানোর জন্য, টাইপ করুন:
$ cc cumsum.c -o cumsum
$ ./cumsum < input > output
UINTMAX_MAX
হয় 18446744073709551615
।
সি কোডটি আমার মেশিনে অর্ডিক কমান্ডের চেয়ে কয়েকগুণ দ্রুত ইনপুট ফাইলের দ্বারা উত্পাদিত হয়:
#!/usr/bin/env python3
import numpy.random
print(*numpy.random.random_integers(100, size=2000000), sep='\n')
আপনি সম্ভবত এরকম কিছু চান:
sort -n <filename> | uniq -c | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'
আদেশের ব্যাখ্যা:
sort -n <filename> | uniq -c
ইনপুট বাছাই করে এবং একটি ফ্রিকোয়েন্সি টেবিল ফেরত দেয়| awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'
আউটপুটটিকে আরও ভাল ফর্ম্যাটে রূপান্তরিত করেউদাহরণ:
ইনপুট ফাইল list.txt
:
4
5
3
4
4
2
3
4
5
আদেশ:
$ sort -n list.txt | uniq -c | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'
Number Frequency
2 1
3 2
4 4
5 2
আপনি এই vim করতে পারেন। ফাইলটি খুলুন এবং নিম্নলিখিত কীস্ট্রোকগুলি টাইপ করুন:
qaqqayiwj@"<C-a>@aq@a:wq<cr>
লক্ষ্য করুন <C-a>
আসলে Ctrl-একটি, এবং <cr>
হয় গাড়ি ফেরত , অর্থাত্ বোতাম লিখুন।
এটি কীভাবে কাজ করে তা এখানে। প্রথমে, আমরা 'এ' রেজিস্টারটি পরিষ্কার করতে চাই যাতে এটির প্রথমবারের মতো কোনও পার্শ্ব প্রতিক্রিয়া না ঘটে। এটি সহজভাবে qaq
। তারপরে আমরা নিম্নলিখিতটি করি:
qa " Start recording keystrokes into register 'a'
yiw " Yank this current number
j " Move down one line. This will break the loop on the last line
@" " Run the number we yanked as if it was typed, and then
<C-a> " increment the number under the cursor *n* times
@a " Call macro 'a'. While recording this will do nothing
q " Stop recording
@a " Call macro 'a', which will call itself creating a loop
এই পুনরাবৃত্ত ম্যাক্রো চলমান হয়ে যাওয়ার পরে, আমরা কেবল :wq<cr>
সংরক্ষণ এবং প্রস্থান করার জন্য কল করি ।
পার্ল ওয়ান-লাইনার:
$ perl -lne 'print $sum+=$_' input.txt
3
7
12
20
সংখ্যাটির 2.5 মিলিয়ন লাইনের সাথে, এটি প্রক্রিয়া করতে প্রায় 6.6 সেকেন্ড সময় নেয়:
$ time perl -lne 'print $sum+=$_' large_input.txt > output.txt
0m06.64s real 0m05.42s user 0m00.09s system
$ wc -l large_input.txt
2500000 large_input.txt
real 0m0.908s
, অনেক ভালো.
একটি সাধারণ ব্যাশ ওয়ান-লাইনার:
x=0 ; while read n ; do x=$((x+n)) ; echo $x ; done < INPUT_FILE
x
বর্তমান লাইন এবং উপরের সমস্ত সংখ্যার সংখ্যার যোগফল।
n
বর্তমান লাইনে নম্বর।
আমরা সব লাইনের উপর লুপ n
এর INPUT_FILE
এবং আমাদের পরিবর্তনশীল তাদের সাংখ্যিক মান যোগ x
এবং প্রতিটি পুনরাবৃত্তির সময় যে সমষ্টি প্রিন্ট করা হবে।
বাশ এখানে কিছুটা ধীর হলেও আপনি কনসোলে আউটপুট প্রিন্ট না করেই 2 মিলিয়ন এন্ট্রি সহ কোনও ফাইলের জন্য এটি প্রায় 20-30 সেকেন্ডের জন্য চালানোর আশা করতে পারেন (এটি আপনি যে পদ্ধতিটি ব্যবহার করেন তা ধীরে ধীরে স্বতন্ত্র)।
@ স্টিল্ড্রাইভারের উত্তরের মতো, তবে bc
পরিবর্তে সামান্য কম আরকেন সহ :
sed 's/.*/a+=&;a/' input | bc
bc
(এবং dc
) সম্পর্কে দুর্দান্ত জিনিসটি হ'ল এগুলি নির্বিচারে নির্ভুলতা ক্যালকুলেটর, সুতরাং কখনই উপচে পড়বে না বা পূর্ণসংখ্যার চেয়ে নির্ভুলতার অভাব ভোগ করবে না।
sed
অভিব্যক্তি ইনপুট রূপান্তরিত:
a+=3;a
a+=4;a
a+=5;a
a+=8;a
এটি তখন দ্বারা মূল্যায়ন করা হয় bc
। a
খ্রিস্টপূর্ব পরিবর্তনশীল স্বয়ংক্রিয় ইনিশিয়ালাইজ প্রতিটি লাইন বাড়তি 0. হয় a
, তারপর স্পষ্টভাবে এটি ছাপে।
real 0m5.642s
1.3 মিলিয়ন লাইনে সেড এই সত্যিই ধীর।