বেসিকস

বেসিকস

লার্নিং অনুশীলনী

ভূমিকা

মৌলিক বিষয়

আমরা এখানে ভাষাটিকে AWK এবং AWK প্রোগ্রাম ইন্টারপ্রেট করে এমন এক্সিকিউটেবলটিকে awk বা gawk নামে ডাকব।

প্যাটার্ন ও অ্যাকশন

একটি AWK প্রোগ্রাম তৈরি হয় প্যাটার্ন-অ্যাকশন জোড়া দিয়ে

pattern1 { action1 }
pattern2 { action2 }
...

একটি প্যাটার্ন ইনপুটের সাথে মেলানোর জন্য একটি রেগুলার এক্সপ্রেশন প্যাটার্ন হতে পারে। এটি এমন যেকোনো এক্সপ্রেশনও হতে পারে যার ফলাফল ট্রু/ফলস মান হয়।

একটি অ্যাকশন হলো এক বা একাধিক AWK কমান্ড। ঘিরে থাকা বন্ধনী দুটি অবশ্যই দিতে হবে।

প্যাটার্নের ফলাফল যদি ট্রু হয়, তাহলে সংশ্লিষ্ট অ্যাকশনটি চালানো হয়।

রেকর্ড ও ফিল্ড

AWK ইনপুটকে একের পর এক রেকর্ড হিসেবে পার্স করে। প্রতিটি রেকর্ড শূন্য বা ততোধিক ফিল্ড-এ ভাগ করা হয়।

ডিফল্ট আচরণ হলো:

  • "রেকর্ড সেপারেটর" হিসেবে নিউলাইন ব্যবহার করে ইনপুটকে রেকর্ডে ভাগ করা হয়, তাই প্রতিটি লাইন হলো একটি রেকর্ড।
  • "ফিল্ড সেপারেটর" হিসেবে হোয়াইটস্পেস ব্যবহার করে রেকর্ডটিকে ফিল্ডে ভাগ করা হয়, তাই প্রতিটি শব্দ হলো একটি ফিল্ড।

প্যাটার্ন ও অ্যাকশন, পরবর্তী অংশ

প্যাটার্ন বাদ দেওয়া যায়; সেক্ষেত্রে প্রতিটি ইনপুট রেকর্ডের জন্য অ্যাকশনটি চালানো হয়।

অ্যাকশনও বাদ দেওয়া যায়; সেক্ষেত্রে ডিফল্ট অ্যাকশন হলো বর্তমান রেকর্ডটি প্রিন্ট করা।

বিশেষ প্যাটার্ন

এমন দুটি বিশেষ প্যাটার্ন আছে যেগুলো প্রায়ই ব্যবহার করা হয়।

  • কোনো ইনপুট ব্যবহার হওয়ার আগে BEGIN সংশ্লিষ্ট অ্যাকশনটি চালায়।
  • সমস্ত ইনপুট ব্যবহার হয়ে যাওয়ার পর END সংশ্লিষ্ট অ্যাকশনটি চালায়।

ফিল্ড ভ্যারিয়েবল

ফিল্ডগুলো বোঝাতে আপনি $1, $2, $3 ইত্যাদি ব্যবহার করেন।

বর্তমান রেকর্ডটি হলো $0।

এখানে আরও কিছু প্রায়ই ব্যবহৃত বিল্ট-ইন ভ্যারিয়েবল আছে।

ইনপুট পার্সিং নিয়ন্ত্রণ করে এমন বিল্ট-ইন ভ্যারিয়েবল
  • RS হলো ইনপুট রেকর্ড সেপারেটর। আগেই বলা হয়েছে, এর ডিফল্ট মান একটি নিউলাইন।
  • FS হলো ইনপুট ফিল্ড সেপারেটর।

এই ভ্যারিয়েবলগুলো প্রায়ই BEGIN অ্যাকশন ব্লকে সেট করা হয়।

তথ্য বহন করে এমন বিল্ট-ইন ভ্যারিয়েবল

প্রোগ্রাম চালানোর সময় AWK এই ভ্যারিয়েবলগুলো স্বয়ংক্রিয়ভাবে সেট করে।

  • NF বর্তমান রেকর্ডে থাকা ফিল্ডের সংখ্যা সংরক্ষণ করে।
    • শেষ ফিল্ডের মান পেতে $NF ব্যবহার করুন।
  • NR বর্তমান রেকর্ড নম্বর সংরক্ষণ করে।
    • একাধিক ইনপুট ফাইল প্রসেস করা হলে, NR এতক্ষণ প্রসেস করা মোট রেকর্ড সংখ্যা ধরে রাখবে।
  • FNR বর্তমান ইনপুট ফাইলের বর্তমান রেকর্ড নম্বর সংরক্ষণ করে।
    • NR আর FNR-এর পার্থক্য বোঝাতে, এখানে একটি কমন AWK আইডিয়ম দেওয়া হলো।
      NR == FNR {action}
      
      এর অর্থ হলো "যদি জমে থাকা রেকর্ড নম্বর বর্তমান ফাইলের রেকর্ড নম্বরের সমান হয়।" এটি শুধু প্রথম ইনপুট ফাইলের রেকর্ডের ক্ষেত্রেই ট্রু হতে পারে।

ট্রুথিনেস

AWK-এ ট্রুথিনেসের ধারণাটি C-এর মতোই।

  • সংখ্যা 0 হলো ফলস।
  • অন্য যেকোনো সংখ্যা হলো ট্রু।

যেহেতু AWK একটি টেক্সট-প্রসেসিং ভাষা, তাই ট্রু/ফলস মান স্ট্রিং-এও প্রসারিত করা হয়েছে।

  • খালি স্ট্রিং "" হলো ফলস।
  • যেকোনো অখালি স্ট্রিং হলো ট্রু।

কমেন্ট

কমেন্ট শুরু হয় # ক্যারেক্টার দিয়ে এবং লাইনের শেষ পর্যন্ত বিস্তৃত থাকে।

উদাহরণ

ইউনিক্স-সদৃশ সিস্টেমে /etc/passwd ফাইলে ব্যবহারকারীদের তথ্য থাকে। প্রতিটি ব্যবহারকারী আলাদা লাইনে বর্ণিত থাকে, আর ফিল্ডগুলো কোলন দিয়ে আলাদা করা থাকে।

ইউজারনেমগুলো তালিকাভুক্ত করতে:

awk '
    BEGIN { FS = ":" }
    { print $1 }
' /etc/passwd

খেয়াল করুন, {print $1} অ্যাকশনে কোনো প্যাটার্ন নেই, তাই এটি প্রতিটি রেকর্ডের জন্য চালানো হয়।

যদি আমরা আউটপুট শুধু সেইসব ব্যবহারকারীর মধ্যে সীমাবদ্ধ করতে চাই যারা লগইন শেল হিসেবে bash ব্যবহার করেন, তাহলে এভাবে করা যায়:

awk '
    BEGIN { FS = ":" }
    $7 == "/bin/bash" { print $1 }
' /etc/passwd

নির্দেশনা

একদা সাইবারস্পেস নামে একটি ব্যস্ত শহর ছিল। সাইবারস্পেস ছিল একটি ডিজিটাল মহানগর, যেখানে প্রতিদিন লক্ষ লক্ষ বাসিন্দা লগইন আর লগআউট করত। এই সব ইউজারের হিসাব রাখতে সাইবারস্পেসে /etc/passwd নামে একটি বিশেষ ফাইল ছিল।

/etc/passwd ফাইলটি ছিল শহরের একটি ফোনবুকের মতো। সিস্টেমে অ্যাকাউন্ট আছে এমন প্রতিটি ইউজারের তালিকা এতে ছিল, সঙ্গে প্রতিটি ইউজার সম্পর্কে কিছু গুরুত্বপূর্ণ তথ্যও:

n ফিল্ড
1 ইউজারনেম
2 পাসওয়ার্ড ("x" মানে নিরাপত্তার জন্য আসল পাসওয়ার্ড অন্য কোথাও সংরক্ষিত থাকে)
3 UID, প্রতিটি ইউজারের অনন্য সংখ্যাসূচক আইডি
4 GID, একটি গ্রুপের অনন্য সংখ্যাসূচক আইডি (সাধারণত UID-এর সমানই হয়)
5 ইউজার তথ্য (সাধারণত ইউজারের পুরো নাম, তবে অন্য তথ্যও থাকতে পারে)
6 হোম ডিরেক্টরি
7 লগইন শেল

ফিল্ডগুলো একটি কোলন অক্ষর দিয়ে আলাদা করা হয়। এটি একটি সাধারণ এন্ট্রি:

glennj:x:1010:1010:Glenn Jackman:/home/glennj:/usr/local/bin/fish

ফাইলটি পরিচালনা করত সিস্টেম অ্যাডমিনিস্ট্রেটরদের একটি দল, যারা নতুন অ্যাকাউন্ট তৈরি, বিদ্যমান অ্যাকাউন্ট হালনাগাদ আর পুরনো অ্যাকাউন্ট মুছে ফেলার দায়িত্বে ছিল। সিস্টেম অ্যাডমিনিস্ট্রেটররাই ছিলেন সাইবারস্পেসের দ্বাররক্ষী, যারা নিশ্চিত করতেন কেবল অনুমোদিত ইউজাররাই সিস্টেমে প্রবেশ করতে পারে।

একদিন দলটিতে যোগ দিতে অ্যালেক্স নামে একজন নতুন সিস্টেম অ্যাডমিনিস্ট্রেটর নিয়োগ পেলেন। অ্যালেক্স কাজটি নিতে উৎসাহী ছিলেন, আর দ্রুত /etc/passwd ফাইলের খুঁটিনাটি শিখে নিলেন। তিনি শিখলেন কীভাবে সিস্টেমে নতুন ইউজার যোগ করতে হয়, ইউজার তথ্য হালনাগাদ করতে হয় আর পুরনো ইউজার মুছে ফেলতে হয়।

অ্যালেক্স যখন /etc/passwd ফাইলে কাজ করছিলেন, তখন তিনি একটি অদ্ভুত বিষয় লক্ষ্য করলেন। কিছু ইউজারের হোম ডিরেক্টরি ছিল অদ্ভুত বা অস্বাভাবিক। কিছু ইউজারের হোম ডিরেক্টরি সেট করা ছিল /dev/null-এ, আবার কারও কারও হোম ডিরেক্টরি সেট করা ছিল এমন সব অদ্ভুত পাথে যা আসলে নেই।

অ্যালেক্স বুঝলেন, এই ইউজারগুলো আসল মানুষ নয়, বরং হ্যাকারদের তৈরি করা ভুয়া অ্যাকাউন্ট। হ্যাকাররা সিস্টেমের একটি ভালনারেবিলিটি কাজে লাগানোর পথ খুঁজে পেয়েছিল, আর সাইবারস্পেসে প্রবেশের জন্য এই ভুয়া অ্যাকাউন্টগুলো তৈরি করেছিল।

অ্যালেক্স জানতেন, তাঁকে ব্যবস্থা নিতে হবে। তিনি /etc/passwd ফাইল বিশ্লেষণ করতে awk ব্যবহার করলেন, আর সব ভুয়া অ্যাকাউন্ট চিহ্নিত করার একটি স্ক্রিপ্ট লিখলেন। এরপর তিনি দলের বাকিদের সঙ্গে মিলে অ্যাকাউন্টগুলো মুছে ফেললেন, আর হ্যাকারদের এসব তৈরি করতে দেওয়া ভালনারেবিলিটিটি প্যাচ করলেন।

অ্যালেক্সের awk ব্যবহারের কৃতিত্বে দলটি ভুয়া অ্যাকাউন্টগুলো চিহ্নিত করে মুছে ফেলতে পারল, আর সাইবারস্পেসকে সবার জন্য নিরাপদ একটি জায়গা করে তুলল। সিস্টেম অ্যাডমিনিস্ট্রেটররা /etc/passwd ফাইল পরিচালনা চালিয়ে গেলেন, এটি হালনাগাদ ও নিরাপদ রাখলেন, আর নিশ্চিত করলেন কেবল অনুমোদিত ইউজাররাই সিস্টেমে প্রবেশ করতে পারে।

এখন অ্যালেক্সের মতো সিস্টেম অ্যাডমিনিস্ট্রেটর হওয়ার পালা আপনার।

Note

এই অনুশীলনীটি সমাধান করতে আপনার আরও কিছু AWK সিনট্যাক্স দরকার হবে।

  • বুলিয়ান অপারেটরগুলো অন্য ভাষাগুলোর মতোই কাজ করে:

    operation example
    AND expr1 && expr2
    OR expr1 || expr2
    NOT ! expr
  • একটি ফাংশন কল করার সিনট্যাক্সও বেশ পরিচিত:

    function greet(name) {
        print "Hello", name
    }
    BEGIN {
        greet("Mary")   # prints "Hello Mary"
    }
    

1. ইউজারনেমগুলো তালিকাভুক্ত করুন

passwd ফাইলের প্রতিটি লাইনের প্রথম কোলন দিয়ে আলাদা করা ফিল্ড প্রিন্ট করার জন্য একটি awk প্রোগ্রাম লিখুন।

2. লাইন নম্বরগুলো প্রিন্ট করুন

এমন একটি awk কমান্ড লিখুন যা ইনপুট ফাইলের প্রতিটি রেকর্ডের লাইন নম্বর প্রিন্ট করে। শুধু লাইন নম্বরটি প্রিন্ট করুন, অন্য কোনো তথ্য নয়।

3. অবৈধ হোম ডিরেক্টরিওয়ালা রেকর্ডগুলো প্রিন্ট করুন।

সাইবারস্পেসে একটি "বৈধ" হোম ডিরেক্টরি /home বা /root দিয়ে শুরু হয়। অবৈধ হোম ডিরেক্টরিওয়ালা ইনপুট ফাইলের রেকর্ডগুলো প্রিন্ট করুন।

4. bash ব্যবহারকারী বৈধ ইউজারগুলো প্রিন্ট করুন

এমন রেকর্ডগুলো প্রিন্ট করুন যেখানে হোম ডিরেক্টরি বৈধ এবং লগইন শেল bash।


সূত্র

ChatGPT-এর সাথে কথোপকথন
GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি একটি নতুন উইন্ডো বা ট্যাবে খোলে
AWK Exercism

বেসিকস শুরু করতে প্রস্তুত?

Exercism-এ সাইন আপ করুন, AWK ট্র্যাকের 3টি কনসেপ্ট92টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।