প্রথমে awk ব্যবহার করে শেষ লাইনে প্রক্রিয়া করুন


11

আমার কাছে একটি ডেটা ফাইল রয়েছে যা আমি awkসর্বশেষ ডেটাপয়েন্টের ভিত্তিতে ব্যবহার করে স্বাভাবিক করতে চাই । এর জন্য, আমি প্রথমে সর্বশেষ ডেটা পয়েন্টটি অ্যাক্সেস করতে চাই, ডেটা স্বাভাবিক করতে, তারপরে স্বাভাবিকভাবে প্রক্রিয়া করি।

নিম্নলিখিত পদ্ধতিটি, tacদুবার ব্যবহার করে, কাজটি করে, তবে, সম্ভবত প্রয়োজনের চেয়ে জটিল।

$ cat file
0 5
1 2
2 3
3 4
$ tac file | awk 'NR==1{norm=$2} {print $1, $2/norm}' | tac
0 1.25
1 0.5
2 0.75
3 1

আমার প্রশ্নটি নিম্নরূপ: কেবলমাত্র খালি ব্যবহার করে কি উপরের ফলাফলটি পাওয়া সম্ভব?

আমি মনে করি উত্তরটি "না, অ্যাডব্লাই দ্বারা ফাইল লাইন স্ক্যান করে স্ক্যান করে" তবে বিকল্পগুলির পরামর্শের জন্য আমি উন্মুক্ত।

উত্তর:


5

আপনি এটিকে জোর করে দু'দিকের সমাধান হিসাবে করতে পারেন:

awk 'FNR == NR { n = $2; next } { print $1, $2/n }' infile infile

যদি আপনার জাভের সংস্করণটি এন্ডফলাইন ব্লকটিকে সমর্থন করে (যেমন জিএনইউ অ্যাজক 4+), আপনি এটি এটি করতে পারেন:

awk 'ENDFILE { n = $2 } FNR != NR { print $1, $2/n }' infile infile

নোট করুন যে seekফাইলটির শেষের দিকে এটি আরও দক্ষ, প্রথমে ক্যামের উত্তর দেখুন

ব্যাখ্যা

প্রথম উদাহরণটি পূর্ববর্তী স্মরণ করে কাজ করে $2, অর্থাত্ যখন স্থানীয় লাইন কাউন্টার ( FNR) বৈশ্বিক লাইন কাউন্টার ( NR) এর সমান হয় তখনই এটি মূল্যায়ন করা হয় । nextকমান্ড পরবর্তী লাইনে অগ্রাহ্য এই ক্ষেত্রে এটি নিশ্চিত করে যে শেষ ব্লক শুধুমাত্র মূল্যায়ন হয় যখন দ্বিতীয় যুক্তি পার্স করা হয়।

দ্বিতীয় উদাহরণে অনুরূপ যুক্তি রয়েছে, তবে এন্ডফিল ব্লকটি গ্রহণ করে যা কোনও ইনপুট-ফাইলের সমাপ্তির পরে মূল্যায়ন করা হয়।


প্রথম উদাহরণটি ঠিক কাজ করে, দ্বিতীয়টি কাজ করে না $ awk --version GNU Awk 3.1.8। আপনি কীভাবে দুটি ইনপুট ফাইল পরিচালনা করেন এবং কী nextকরে তার একটি খুব ছোট ব্যাখ্যা যুক্ত করতে পারেন ?
বার্নহার্ড

1
@Bernhard: সম্পাদনা দেখুন
থর

6

যদি আপনার ডেটা উত্স এমন কোনও ফাইল যা একাধিকবার পড়তে পারে (যেমন এটি কোনও স্ট্রিম নয়), আপনার প্রথমে tail(1)শেষ লাইনটি থেকে আপনার পছন্দসই ডেটা পাওয়ার জন্য ব্যবহার করা উচিত এবং ফাইলটির ক্রমগত ক্রিয়াকলাপের জন্য এটি অবাক করা উচিত। tailফাইলের শেষের দিকে সর্বশেষ তথ্যটি না পড়ার আগে শেষ পংক্তিটি পড়তে চাইবে।

awk -v norm=$(tail -n 1 file | cut -d' ' -f2) '{print $1, $2/norm}' file

এটি বড় ফাইলগুলিতে একটি বড় জয় হবে যেখানে পুরো ফাইলটি বাফার ক্যাশে ফিট করে না (যার অর্থ এটি প্রতিটি পাসের জন্য একবারে দুবার ডিস্ক থেকে পড়তে হবে), এবং স্ক্যান করার প্রয়োজন না পড়ে একটি অল্প পরিমাণে সহায়তা করবে শেষ লাইন পেতে ইনপুট। ছোট ফাইলগুলি দ্বি-পাসের পদ্ধতির পক্ষে খুব বেশি পার্থক্য না দেখায়।


3

আপনি এগুলিকে একটি অ্যারেতে লোড করতে এবং পিছন দিকে পড়তে পারেন:

awk '{x[i++]=$0} END{for (j=i-1; j>=0;) print x[j--] }'

আপনি এটি আরও দক্ষতার সাথে করতে পারেন তবে এই ধরণের চিত্রটি awkবোঝায় যে এটির জন্য সঠিক সরঞ্জামটি কেন নয়। tacযেখানে পাওয়া যায় সেখানে ব্যবহার চালিয়ে যান , জিএনইউ ট্যাক সাধারণত এই কাজের জন্য বিভিন্ন সরঞ্জামের মধ্যে দ্রুততম হয়।


আমি সম্মত, একটি- forলুপ ইন ব্যবহার করা awkসমাধান নয়।
বার্নহার্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.