ما به زبان با نام 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
روزی روزگاری، شهر پرجنبوجوشی به نام Cyberspace وجود داشت.
Cyberspace یک کلانشهر دیجیتال بود که هر روز میلیونها ساکن به آن وارد و از آن خارج میشدند.
برای پیگیری همهی این کاربران، Cyberspace فایل ویژهای به نام /etc/passwd داشت.
فایل /etc/passwd مثل دفترچه تلفن شهر بود.
هر کاربری را که روی سیستم حساب داشت فهرست میکرد، همراه با اطلاعات مهمی دربارهی هر کاربر:
| n | فیلد |
|---|---|
| ۱ | نام کاربری |
| ۲ | گذرواژه («x» نشان میدهد که گذرواژهی واقعی برای امنیت جای دیگری ذخیره شده است) |
| ۳ | UID، شناسهی عددی یکتای کاربر |
| ۴ | GID، شناسهی عددی یکتای گروه (معمولاً همان UID) |
| ۵ | اطلاعات کاربر (معمولاً اسم کامل کاربر، اما میتواند اطلاعات دیگری هم دربر داشته باشد) |
| ۶ | پوشهی خانه |
| ۷ | شل ورود |
فیلدها با کاراکتر دونقطه از هم جدا میشوند. این یک ورودی معمولی است:
glennj:x:1010:1010:Glenn Jackman:/home/glennj:/usr/local/bin/fish
فایل را تیمی از مدیران سیستم اداره میکردند که مسئول ساختن حسابهای جدید، بهروزرسانی حسابهای موجود و حذف حسابهای قدیمی بودند. مدیران سیستم دروازهبانان Cyberspace بودند و مطمئن میشدند که فقط کاربران مجاز به سیستم دسترسی داشته باشند.
یک روز، مدیر سیستم تازهای به نام Alex استخدام شد تا به تیم بپیوندد.
Alex از پذیرفتن این کار هیجانزده بود و خیلی زود همهی ریزهکاریهای فایل /etc/passwd را یاد گرفت.
یاد گرفت چطور کاربران جدید به سیستم اضافه کند، اطلاعات کاربران را بهروزرسانی کند و کاربران قدیمی را حذف کند.
وقتی Alex داشت روی فایل /etc/passwd کار میکرد، به نکتهی عجیبی پی برد.
پوشهی خانهی بعضی کاربران عجیب یا غیرمعمول بود.
پوشهی خانهی بعضی کاربران روی /dev/null تنظیم شده بود و پوشهی خانهی بعضی دیگر روی مسیرهای عجیبی که اصلاً وجود نداشتند.
Alex فهمید که این کاربران افراد واقعی نیستند، بلکه حسابهای جعلیای هستند که هکرها ساختهاند. هکرها راهی پیدا کرده بودند که از یک آسیبپذیری در سیستم سوءاستفاده کنند و این حسابهای جعلی را ساخته بودند تا به Cyberspace دسترسی پیدا کنند.
Alex میدانست که باید دست به کار شود.
او از awk استفاده کرد تا فایل /etc/passwd را تحلیل کند و اسکریپتی نوشت که همهی حسابهای جعلی را شناسایی کند.
سپس با بقیهی اعضای تیم همکاری کرد تا این حسابها را حذف کنند و آسیبپذیریای را که در وهلهی اول به هکرها امکان ساخت آنها را داده بود، رفع کنند.
به لطف استفادهی Alex از awk، تیم توانست حسابهای جعلی را شناسایی و حذف کند و Cyberspace را به جای امنتری برای همه تبدیل کند.
مدیران سیستم همچنان فایل /etc/passwd را مدیریت میکردند، آن را بهروز و امن نگه میداشتند و مطمئن میشدند که فقط کاربران مجاز به سیستم دسترسی داشته باشند.
حالا نوبت شماست که مثل Alex مدیر سیستم باشید.
در اینجا چند نکتهی اضافی از نحوهی نگارش AWK را میبینید که برای حل این تمرین به آنها نیاز دارید.
عملگرهای منطقی شبیه زبانهای دیگر هستند:
| عمل | مثال |
|---|---|
| AND | expr1 && expr2 |
| OR | expr1 || expr2 |
| NOT | ! expr |
فراخوانی یک تابع نحوهی نگارش آشنایی دارد:
function greet(name) {
print "Hello", name
}
BEGIN {
greet("Mary") # prints "Hello Mary"
}
یک برنامهی awk بنویسید که اولین فیلد جداشده با دونقطه را برای هر خط در فایل passwd چاپ کند.
یک دستور awk بنویسید که شمارهی خط هر رکورد در فایل ورودی را چاپ کند. فقط شمارهی خط را چاپ کنید، نه هیچ اطلاعات دیگری.
در Cyberspace، پوشهی خانهی «معتبر» با /home یا /root شروع میشود.
رکوردهای فایل ورودی را که پوشهی خانهی نامعتبر دارند چاپ کنید.
رکوردهایی را چاپ کنید که پوشهی خانهشان معتبر است و شل ورودشان bash است.