الثلاثاء، 28 سبتمبر 2010

مقدمة في لغة AWK

بسم الله الرحمن الرحيم
مقدمة في لغة
AWK

  • ما هو AWK
هو لغة برمجية تتعامل مع النصوص بشكل خاص و تستخدم بشكل كبير في أنظمة Unix , و أسم اللغة أستنبط من أسماء للمبرمجين الذين أبتكروا اللغة (Alfred V.Aho,Brian W. Kernighan,Peter J. Weinberger). 


  • كيفية استخدام AWK
لنبدأ بشرح النمط العام لأوامر awk بهذا المثال البسيط:
awk  'BEGIN{print "Test Program"}'


هذا البرنامج يطبع جملة "Test program" , البرنامج يبدأ بأسم معالج لغة awk ثم بعلامة التنصيص التي تخبر المعالج ببداية الأوامر , و أوامر AWK لها نمط معين وهو:

pattern{Action}
pattern{Action}
 
و نعني بال "pattern" هو الشرط المراد مطابقته , و ال "action" هو الأمر المراد تنفيذه في حال مطابقة الشرط و نرى في المثال الأول أننا و ضعنا كلمة "BEGIN" أي ان الأمر يجب أن ينفذ في بداية الملف , وفي مكان الأمر و ضعنا كلمة "print" لطباعة الجملة "Test program".
و الآن ستأتي على استخدام الحروف الخاصة ($0-$1-$2-...)التي تستخدم لتحكم في طريقة عرض البيانات:

$0-طباعة السطر كامل
$1-طباعة العمود الأول
$2-طباعة العمود الثاني
وهكذا تستطيع زيادة قيمة العمود على حسب عدد الأعمدة الموجود لديك , و سوف نقرب الفكرة بالمثال التالي:

echo "This is Test"|awk '{print $0}'


جرب أن تزيد قيمة $0 و سترى تغير المخرجات كالتالي:
$0-This is Test
$1-This
$2-is
$3-Test
لنفترض أنك تريد طباعة العمود الأول و الثالث:
echo "This is Test"|awk '{print $1,$3}'

يعتمد awk على المسافة أو "TAB" للفصل بين الخلايا في السجل , و لكن يمكن تغير طريقة الفصل على حسب الطريقة المستخدمة في ملف البيانات باستخدام "FS" التي تعني كما في المثال التالي:
echo 'This-is-Test'|awk 'BEGIN{FS="-"}{print $2}'
يجب أن نلاحظ أننا يجب أن نضع قيمة المتغير FS بعد BEGIN .

3-العمليات المنطقية

الجدول التالي يظهر العمليات المنطقية و وسائل المقارنة:
< 
أصغر من
< =
أصغر من أو يساوي
==
يساوي
=!
لا يساوي
> =
أكبر من أو يساوي
>
أكبر من
~
يساوي (يستخدم مع النصوص)
!~
لا يساوي (يستخدم مع النصوص)


لكي نبدأ بالتطبيق أحفظ الجدول التالي على حاسبك بهيئة ملف نصي بأسم "list.txt":


Joe          408 555-5553     cell


Joe          415 555-8755     home


Sue Ann      202 555-3412     home


Minh         619 555-7685     office


Jane         408 555-1675     office


Jane         408 555-5543     cell


Renee        415 555-0542     cell


Julie        650 555-2912     cell


Sam          408 555-1234     home


Ray          408 555-6699     home


Bill         503 555-6480     cell


Bill         503 555-1100     office


Darin        202 555-3430     office


Fred         415 555-2127     cell

المثال الأول:
awk '$2==503 {print $0}' list.txt
output:
Bill         503 555-6480     cell
Bill         503 555-1100     office
سيقوم البرنامج بالبحث في العمود الثاني عن القيمة 503





المثال الثاني:
awk  '$1 ~/joe/ {print $0}' list.txt
                                                                                                                                                                       
output:
Joe          408 555-5553     cell
Joe          415 555-8755     home

سيقوم البرنامج بطباعة السطور المحتوية على أسم "joe" في الحقل الأول

المثال الثالث:
awk  '~!/Bill/ {print $0}' list.txt
طباعة السطور التي لا تحتوي على الاسم "Bill"

المثال الرابع:

لنفترض أننا نريد طباعة السطر الذي توجد فيه الاسم "Bill" و "cell"

awk  '/Bill/ && /cell/ {print $0}' list.txt
تلاحظ أننا استخدمنا "&&" بين الشرطين ,"&&" تعني AND

المثال الخامس:

أذا أردنا أن نطبع السجلات حيث الاسم "Joe" أو "Jane" يجب أن نظيف || التي تعني "OR" كما في الأمر كالتالي

awk  '/Jane/ || /Joe/ {print $0}' list.txt


4-المتغيرات:
تستطيع أنشاء المتغيرات و التعامل معها في awk ، لإنشاء المتغير هنالك طريقتان الأولى:
awk –v name="Bill" 'BEGIN {print name}'
هذه الطريقة تسمح بالتعامل مع متغيرات النظام كما في المثال التالي:
name=`whoami`
awk –v name=$name 'BEGIN{print "Wellcome",name

يقوم المثال باستخدام الأمر whoami لأخذ أسم المستخدم في نظام لينكس و بعد ذلك استخدمنا (name=$name) لتحويل المتغير إلى متغير خاص ب "Awk".

الطريقة الثالثة:

awk  'BEGIN{name="Khalid"}{print "Wellcome",name}'

أذا وضعت الحرف "$" قبل المتغير فأن المعالج سيتعامل معه على أنه متغير سجل ($0,$1,$2) كالمثال التالي:

awk 'BEGIN{x=1}{print $x}' list.txt











5-العمليات الحسابية

العملية
الشرح
+
الجمع
-
الطرح
*
الضرب
/
القسمة
%
باقي القسمة (0 في حالة لم يكن هنالك باقي للقسمة , 1 أذا كان هنالك باقي)
()
أعطاء الأولية لعملية التي بين القوسين


تستطيع استخدام awk كحاسبة مبسطة كما في المثال التالي:
awk 'BEGIN{print 21*23}'
تستطيع استخدام العمليات الحسابية على المتغيرات و هناك تعابير حسابية كما في الجدول التالي:

العملية
الشرح
+=
إضافة عدد للمتغير
-=
طرح عدد للمتغير
*=
ضرب عدد بمتغير
/=
قسمة عدد بمتغير
%=
عملية باقي القسمة
++
زيادة قيمة المتغير 1
--
إنقاص قيمة المتغير 1


نستطيع أستخدمها كما في المثال التالي:
awk –v x=2 'BEGIN{print x *=12}'

6-المتغيرات الخاصة بلغة "AWK"
NR:يظهر رقم السجل الحالي
NF:يظهر عدد الحقول في السجل الحالي
FILENAME:أسم ملف الذي يحتوي على السجلات
FS:"Filed separator" المحرف المستخدم في فصل الحقول في الملف المستخدم
RS:المحرف المستخدم لفصل السجلات في الملف المستخدم , الأعداد الافتراضي هي محرف السطر الجديد
OFS: المحرف المستخدم لفصل الحقول في المخرجات
ORS: المحرف المستخدم لفصل السجلات في المخرجات

سنبدأ باستخدام المتغيرات , وفي المثال الأول سنقوم بإنشاء برنامج يطبع السجل السادس في ملف "List.txt" , كما سيعرض أسم الملف المستخدم في حفظ السجلات:

awk ' NR==6 {print FILENAME,":",$0}' list.txt
المثال الثاني يقوم بطباعة السجلات بعد تغير المحرف المستخدم في فصل المخرجات (السجلات) كما سيظهر عدد السجلات في الملف:
awk 'BEGIN{OFS=":";ORS="\n"}{print $1,$2,$4}END{print "\n\n",FILENAME,"Record number:",NR}' list.txt

تلاحظ في نهاية الأمر الكلمة "END" هذه الكلمة تدل على أن الأمر يجب أن ينفذ في نهاية البرنامج و الذي قمنا به هو طباعة NR الذي يحمل عدد السجلات.





7-القرارات و الحلقات التكرارية

1) القرارات if..else

بنية الجملة "if..else" بسيط جدا فهي تقوم بمقارنة أو مطابقة شرط يضعه المبرمج ففي حالة مطابقة الشرط يقوم بتنفيذ الأمر المعين من قبل المبرمج :

{ (الشرط أو المقارنة)if
do this action}
{ (الشرط أو المقارنة)else
do this action}

لاحظ أننا نقدر على الاستغناء عن else أذا لم يكن هنالك حاجة لها و نستطيع أن نستخدم else بدون الشرط أو المقارنة , الآن مع مثال عملي لبرنامج يقوم بإيجاد باقي القسمة و طباعة أذا ما كان الرقم زوجي أو فردي :
awk 'BEGIN{if(13%2==0){print "13 is even"}else{print "13 is odd"}'
2)الجملة التكرارية while
الجملة التكرارية "while" ستقوم بالأمر المعين من المبرمج ألى أن ينتفي الشرط المحدد أو المقارنة وهذه هي البنية للأمر:
{(الشرط أو المقارنة)while
the action}
وفي هذا المثال البسيط سيقوم البرنامج بطباعة الأرقام من 1 ألى 10:
awk 'BEGIN{x=1;while(x<=10){print x;x++}'
تلاحظ أننا قمنا بفصل الأوامر باستخدام الفاصلة المنقوطة ";" في البنية البرمجية الواحدة في هذه الحالة "BEGIN" ويمكن أستبدلها عنها في الأمر أو السكريبت بمحرف السطر الجديد , في حالة نسيانها سيؤدي ذلك إلى خطأ في البرنامج.



3)الجملة التكرارية (do..while)

يوجد تشابه كبير بين (while) و (do..while) الفرق الوحيد بينهما أن (do..while) تقوم بتنفيذ الأمر أولا بعد ذلك تقوم بالمقارنة أذا ما تطابق الشرط , في حالة التطابق تتكرر الحلقة ألا أن ينتفي الشرط, سأقوم بإعادة كتابة المثال السابق باستخدام (do..while) مع تغير قيمة المتغير ألى 11 لكي تستطيع فهم الفكرة:
awk 'BEGIN{x=11;do{print x;x++}while(x<=10)}'
تلاحظ أن البرنامج طبع الرقم 11 ثم توقف عن العمل لعدم مطابقة الشرط.

4)الجملة التكرارية (for)
هذه الجملة من أسهل الجمل التكرارية , و تتشكل هذه الجملة من ثلاث معاملات و هي :
1)المتغير وهو الذي توضع فيه قيمة العداد
2)الشرط , الذي تستمر الحلقة أذا لم ينتفي
3)المؤثر و يمكن استعمال اي عملية حسابية و لكن في الغالب تكون زيادة أو نقصان المتغير
وهذا هو مثال على هذه التركيبة:

{ (المؤثر,الشرط,المتغير)for
The Action
}
و في المثال التالي سيقوم البرنامج بطباعة السجلات من 2 إلى 4:
awk '{for(x=2;x<=4;x++){print $x}{print "\n"}}' list.txt
سيقوم البرنامج بزيادة قيمة المتغير x من 2 ألى أن تساوي 4 ثم يتوقف البرنامج و تعاد هذه الحلقة على جميع السجلات في الملف , لقد وضعنا الإشارة $ قبل المتغير للدلالة أنه رقم حقل, , وبعد انتهاء الحلقة قمنا بوضع {print "\n"} لطباعة سطر جديد خالي للحفظ تنسيق البيانات.



5-التحكم بجمل التكرار بواسطة break و continue:

تستخدم break و continue في التحكم في الحلقات التكرارية,لنبدأ بشرح break هذه الكلمة المحجوزة تستخدم في الخروج من الجمل التكرارية , قد تستوضح الفكرة بالمثال التالي الذي يستخدم الحلقة التكرارية for:
awk 'BEGIN{for(x=1;x<=10;x++){if(x==4){print "\nloop ended x=4";break} } } '
ترى أن شرط الحلقة التكرارية أن x<=10 و لكننا وضع شرط جملة التحكم x==4 و عند مطابقة الشرط تطبع الجملة و نخرج من الحلقة التكرارية , الأن جرب نفس المثال لكن بدون break ستلاحظ ان الحلقة تستمر ألى أن ينتفي شرط الجملة التكرارية
awk 'BEGIN{for(x=1;x<=10;x++){if(x==4){print "\nloop ended x=4"} } } '
و الآن إلى استخدام continue , أن هذه الأمر يستخدم لتجاهل الأوامر التي تأتي بعده في الحلقات التكرارية كما في المثال التالي :
awk 'BEGIN{for(x=1;x<=10;x++){continue; print "This text will not show"}'
لن يظهر النص الموجود في الأمر print لوجود continue قبله , وفي المثال التالي سيقوم البرنامج بطباعة الأرقام الزوجية في السلسة الرقمية من 1 ألى 10:
awk 'BEGIN{for(x=1;x<=10;x++){if(x%2==0){print x,"divided by 2";continue} print x,"not divided by 2"} }'
جرب نفس الأمر بدون الكلمة continue ستلاحظ إن معطيات البرنامج غير صحيحة .
8-الملفات التفسيرية script
تستطيع أنشاء برامج على شكل سكربيت باللغة awk , الشيء المختلف هو أنك يجب أن تضع هذه الجملة في بداية الملف :
#!/usr/bin/awk
أو تستطيع أن تقوم به مباشرة في terminal:
awk –f  Program_name
تستطيع أضافة أسم الملف المراد تطبيق البرنامج بعد أسم البرنامج , وهذا مثال بسيط يقوم بطباعة الملف list.txt
#!/usr/bin/awk –f
#This is comment
BEGIN{print "Test program:"}
{print $0}
END{print "The file name:",FILENAME,"\nThe number of record:",NR}
تستطيع أضافة تعليقاتك بعد علامة "#" , بعد حفظ الملف يجب أن تحوله إلى ملف تنفيذي في لينكس يجب تستخدم الأمر:
chmod +x program_name
تستطيع تنفيذ الأمر بواسطة "اسم البرنامج/." وبعدها أسم الملف المراد تنفيذه في هذه الحالة list.txt.

9-الدوال المعرفة في لغة AWK
تحتوي لغة awk  على دوال مدمجة لزيادة القدرات المعطاة للمبرمج و سو نبدأ بالدوال الحسابية:
الدالة
الشرح
atan2(y,x)
أعطاء قيمة "مقابل الظل"
cos(x)
أعطاء قيمة جيب التمام
exp(x)
أعطاء قيمة الدالة الأسية
int(x)
أعطاء القيمة الصحيحة لمتغير
log(x)
أعطاء قيمة اللوغاريتم
rand()
تعيد هذه الدالة رقم عشوائي تقع قيمته بين 1 و 0
sin(x)
حساب جيب الزاوية
sqrt(x)
أعادة قيمة الجذر التربيعي للمتغير
srand(x)
أعطاء القيمة المستخدمه في أنشاء الرقم العشوائي في الدالة rand()

و الأن تأتي على شرح الدوال المستخدمه في  التعامل مع النصوص:
الدالة
الشرح
gsub(r,s,t)  -gsub(r,s)
تقوم هذه الدالة بالبحث عن القيمة "r"  و أستبدلها بالقيمة "s"  في المتغير "t"  و في حالة عدم وجود متغير سيطبق الأمر على المتغير $0
index(s,t)
أذا كان  "t" جزء من المتغير النصي "s" يعيد الموقع الذي يبدأ في المتغير النصي "t"  و في حالة عدم العثور عنه يرجع القيمة صفر
length(x)
يرجع طول السلسة النصية "x"
match(s,r)
يرجع قيمة موقع "r"  في السلسة النصبة "s"
split(s,a,r)
يقسم السلسة النصية "s" بأستخدام النمط "r" وحفظ الناتج في المصفوفة "r"
tolower(s)
تحويل السلسة النصية ألى حالة الحروف الكبيرة
toupper(s)
تحويل السلسة النصية ألى حالة الحروف الصغير

10-أنشاء الدوال في awk
تستطيع أنشاء الدوال المعرفة من قبل ببساطة باستخدام الكلمة المفتاحية "function"  ويكون الشكل العام لدالة مثل المثال التالي:
 (المتغيرات) function test1
{ Action
}

تستخدم الكلمة المفتاحية "return"  لإعادة  قيمة من الدالة كما في المثال التالي:
#!/usr/bin/awk -f
function square(n)
return n*n
}
#This is the end of the function
BEGIN{print "The square of 3 is",square(3)}

في هذا المثال عرفنا الدالة "square" التي تعيد القيمة التربعية لمتغير "n" , كما تستطيع تعريف الدالة من دون المتغير كما في المثال التالي:
#!/usr/bin/awk  -f
function message(){
print "Welcome to awk"
}
BEGIN{message()}

تقوم الدالة بطباعة الرسالة "Welcome to awk" و لا تحتاج لأي متغيرات .

11-المصفوفات
تستخدم لغة awk  المصفوفات الترابطية و الفرق الوحيد بين المصفوفات الترابطية و المصفوفات العادية هو أنها تستخدم سلاسل نصية كقيمة دليلة بدل قيمة رقمية كما في المصفوفات العادية كما في المثال التالي:
arrayname[string]=value
arrayname:أسم المصفوفة
string:السلسة النصية المستخدمة كقيمة دليلة (index)
value:هي القيمة المسندة للعنصر
يتم الوصول ألى عناصر بأستخدام الجملة البرمجية for..in كما في المثال التالي:
for (var in arrayname) {
action
}
var:أسم أي متغير
in:كلمة برمجية
arrayname:أسم المصفوفة
action: الأوامر المراد تنفيذها على عناصر المصفوفة
هذه الحلقة التكرارية تقوم بتنفيذ الأوامر على مجموعة العناصر المرتبطة بالسلاسل النصية المعينة كدليل (index)
-تستطيع حذف أي قيمة في المصفوفة باستخدام الكلمة البرمجية delete  كما في المثال التالي:
delete arrayname[index]
يجب ان تلاحظ أن awk  لا تحتوي على أمر يستطيع حذف المصفوفة بالكامل لذا يجب الأستعاضه بالأمر التالي:
for(var in arrayname){
delete array[var]
}
يقوم الأمر بحذف عناصر المصفوفة بالترتيب
-          لنبدأ بالتطبيق العلمي , باستخدام هذا البرنامج البسيط الذي يحسب تكرار الأسم في الملف list.txt
awk '{name[$1]++} END{ for(var in name){ print var,":",name[var]}}'

 البرنامج يقوم بإنشاء مصفوفة بأسم (name) ثم باستخدام الأسماء في السطر الأول كقيمة كدليلة (index) ثم بإضافة واحد كقيمة له وفي حالة تكرار الاسم يزيد البرنامج قيمة المتغير واحد بهذا نستطيع أيجاد تكرار الاسم  ثم  في نهاية البرنامج يطبع الاسم (القيمة الدليل) ثم قيمة المتغير الذي هو عدد تكرار الأسم
ثم الأن لمثال يمكننا من عرض السجلات في الملف بالعكس , أي نعرض السجلات من الأخير ألى الأول :
awk '{a[i++]=$0}END{for(j=i-1;j>=0;){print a[j--]}' list.txt

يقوم البرنامج أولا بإسناد متغير كقيمة دليلة و زيادة قيمة مع كل سجل و بعد ذلك يقوم بإسناد القيمة j في الحلقة التكرارية التي تساوي (i-1) ثم طباعة عناصر المصفوفة و إنقاص قيمة "j"  إلى أن تساوي القيمة الدليلة لأول عنصر في المصفوفة (j=0)











تم بحمد الله تعالى














هناك 10 تعليقات:

  1. رحم الله والديك

    ردحذف
    الردود
    1. و رحم الله و الديك
      و يزاك الله خير

      حذف
  2. من اروع واعظم شروحات awk باللغه العربيه شكرا شكرا من الاعماق

    ردحذف
  3. سلام عليكم

    عمل رااائع ، بارك الله فيك

    ردحذف
    الردود
    1. و عليكم السلام و رحمة الله

      جزاك الله خير

      حذف
  4. الشرح روعه ماشاء الله
    انا فهمت :)
    بس مش عارفه اربط بينه وبين الns2
    وازلى استعمله مثلا عشان احسب الdelay time ?

    ردحذف
  5. لم اتوقع أبدا وجود شرح شامل + واضح .. جزاك الله خيرا وكتبها في موازين حسناتك

    ردحذف
  6. جزاك الله خيرا يا اخي في الله

    ردحذف