مرحباً بك بمدونتنا

Our Company Logo

كيفية استخدام لغة AWK للتعامل مع النصوص في لينكس

تتّبع الأدوات المساعدة في لينِكس فلسفة Unix من ناحية تصميمها عادةً، حيث يُوصى بأن تكون الأدوات صغيرة، أن تستخدم ملفّات نص مُجرَّد plain text للدخل input والخَرْج output، وأن تعمل بالأسلوب التركيبي modular manner، ونمتلك بسبب هذا الإرث legacy وظيفة رائعة لمعالجة النّصوص مع أدوات مثل sed وawk.
AWK-linux.thumb.png.4e2533c16d36d3a0a36d
سنناقش في هذا الدّرس awk، والتي هي لغة برمجة ومُعالِج نصوص على حدٍّ سواء يُمكن استخدامها للتعامل مع بيانات النّصوص بطرق مفيدة جدًّا، سنناقش هذا على Ubuntu 12.04 VPS ولكن ينبغي أن يعمل بنفس الطريقة على أي نظام لينِكس حديث.

الصياغة الأساسية Basic Syntax

يتم تضمين الأمر awk افتراضيًّا في جميع أنظمة لينِكس الحديثة، لذا لن نحتاج إلى تثبيته لكي نبدأ باستخدامه.
يكون awk مفيدًا أكثر عند التعامل مع ملفات نصيّة مُنسَّقة بطريقة متوقعة، فعلى سبيل المثال يكون ممتازًا في تحليل parsing والتعامل مع البيانات المجدولة، فهو يعمل على الأسطر سطرًا تلو الآخر وبالتكرار عبر كامل الملف.
يستخدم awk افتراضيًّا الفواصل whitespaces (المسافات spaces، tabs، إلخ) للفصل بين الحقول، ولحسن الحظ تستخدم معظم ملفّات الإعدادات على نظام لينِكس هذه الصّيغة.
الصيغة الأساسيّة لأمر awk هي:
AWK '/ search_pattern / {action_to_take_on_matches. another_action. } ' file_to_parse
نستطيع إمّا إزالة قسم البحث search أو قسم الإجراء action من أي أمر awk، إنّ الإجراء الافتراضي الذي يتم اتخاذه إن لم نقم بكتابة القسم “action” هو الطباعة “print”، والذي يقوم ببساطة بطباعة كافّة الأسطر الموافقة.
إن لم نقم بكتابة القسم “search” يُنفِّذ awk الإجراء المُدرَج في كل سطر.
أمّا إن قمنا بكتابتهما معًا فيستخدم awk قسم البحث search ليقرّر إذا ما كان السّطر الحالي يعكس النمط pattern المطلوب، ومن ثمّ يُنفِّذ الإجراءات على الأمور المُوافِقة له.

استخدامات بسيطة

نستطيع استخدام awk في أبسط أشكاله مثل cat ليطبع ببساطة جميع أسطر ملف نصّي على الشّاشة.
فلنطبع ملف fstab لخادومنا، والذي يعرض أنظمة الملفّات filesystems التي يعرفها:
AWK '{الطباعة}'  / الخ / fstab
# / الخ / fstab: ثابتة معلومات نظام الملفات. 
# 
# استخدام "blkid" لطباعة المعرف الفريد عالميا ل 
# الجهاز، هذا يمكن أن تستخدم مع UUID = باعتبارها وسيلة أكثر قوة لتسمية الأجهزة 
# يعمل حتى إذا تم إضافة أقراص وإزالتها. انظر fstab (5). 
# 
# 
بروك / بروك بروك nodev ، noexec ، nosuid 0  0 
# / كان على / ديف / vda1 أثناء التثبيت 
UUID = b96601ba - 7d51 - 4c5f - bfe2 - 63815708aabd  / noatime EXT4 ، أخطاء = الفرس البديل - ريال عماني 0  1
لا يفيدنا هذا كثيرًا، فلنجرّب قدرات awk في ترشيح filtering البحث:
AWK '/ UUID /'  / الخ / fstab
# الجهاز، هذا يمكن أن تستخدم مع UUID = باعتبارها وسيلة أكثر قوة على سبيل المثال أجهزة 
UUID = b96601ba - 7d51 - 4c5f - bfe2 - 63815708aabd  / noatime EXT4 ، أخطاء = الفرس البديل - ريال عماني 0  1
وكما نرى يطبع awk الآن الأسطر التي تحتوي "UUID" فقط، بإمكاننا التخلّص من سطر التعليق comment غير المهم عن طريق تحديد أنّ "UUID" يجب أن تتواجد في بداية السّطر:
AWK '/ ^ UUID /'  / الخ / fstab
UUID = b96601ba - 7d51 - 4c5f - bfe2 - 63815708aabd  / noatime EXT4 ، أخطاء = الفرس البديل - ريال عماني 0  1
نستطيع بشكل مشابه استخدام قسم الإجراء action لتحديد أي قطع من المعلومات نريد طباعتها، على سبيل المثال لطباعة العمود الأول فقط نستطيع كتابة:
AWK '/ ^ UUID / {طباعة $ 1؛}  / الخ / fstab
UUID = b96601ba - 7d51 - 4c5f - bfe2 - 63815708aabd
يمكننا الرجوع لكل عمود (لأنّها مفصولة بفراغ بينها) عن طريق متغيرات variables مرتبطة برقم عمودها، على سبيل المثال نستطيع الرجوع للعمود الأول بواسطة المتغير 1$، والرجوع لكامل السّطر بواسطة المتغير 0$.

متغيرات awk الداخلية والتنسيق الموسع Expanded Format

يستخدم awk بعض المتغيّرات الدّاخليّة internal variables لتعيين قطع معيّنة من المعلومات بينما يقوم بمعالجة الملف.
إنّ المتغيّرات الدّاخليّة التي يستخدمها awk هي:
  • FILENAME: يُرجِع ملف الدّخل input الحالي.
  • FNR: يُرجِع عدد التسجيلات record الحاليّة نسبة لملف الدّخل الحالي، على سبيل المثال إن كُنّا نملك ملفّين للدخل فسيخبرنا هذا المتغيّر بعدد التسجيلات لكل ملف بدلًا من أن يخبرنا بالمجموع الكلّي.
  • FS: فاصل الحقل الحالي المُستخدَم للدلالة على كل حقل في التسجيل، يتم تعيينه افتراضيًّا إلى مسافة whitespace.
  • NF: عدد الحقول في التسجيلات الحاليّة.
  • NR: عدد التسجيلات الحاليّة.
  • OFS: فاصل الحقل للبيانات المُخرَجة، يتم تعيينه افتراضيًّا إلى مسافة whitespace.
  • ORS: فاصل التّسجيلات للبيانات المُخرَجة، وهو بشكل افتراضي سطر جديد.
  • RS: فاصل التّسجيلات المُستخدَم لتمييز التّسجيلات المنفصلة في ملف الدّخل، وهو بشكل افتراضي سطر جديد.
نستطيع تغيير قيم هذه المتغيّرات بحسب رغبتنا لتوافِق احتياجات ملفّاتنا، نقوم بذلك عادةً خلال طور التهيئة لمعالجة awk.
يقودنا هذا إلى مفهوم هام آخر، إنّ صياغة awk مُعقَّدة أكثر بقليل ممّا شاهدناه في البداية، حيث توجد أيضًا كُتَل blocks اختياريّة BEGIN وEND والتي يُمكن أن تحتوي على أوامر ليتم تنفيذها قبل وبعد معالجة الملف على التوالي.
يجعل هذا من صيغتنا المُوسَّعة تبدو مشابهة لما يلي:
AWK "BEGIN {العمل؛ }
/ بحث / {العمل؛ }
END {العمل؛ } ' input_file
إنّ الكلمات المفتاحيّة BEGIN وEND هي في الواقع مجرّد مجموعات مُحدّدة من الشّروط conditions تمامًا مثل مُعامِلات parameters البحث، فهي تتوافق مع الشّروط: قبل معالجة المستند وبعد معالجته.
ويعني هذا أنّه بإمكاننا تغيير بعض المتغيّرات الداخليّة في القسم BEGIN، فعلى سبيل المثال الملفetc/passwd/ مفصول بواسطة نقطتين (:) بدلًا من مسافة، وإن أردنا طباعة العمود الأول من هذا الملف نستطيع كتابة ما يلي:
سودو AWK "BEGIN {FS =" "؛ }
{طباعة $ 1؛ } '  / الخ / باسود
جذر
الخفي
بن
تميز الكلية
مزامنة
ألعاب
رجل
. . .
نستطيع استخدام الكُتَل BEGIN وEND لطباعة معلومات بسيطة حول الحقول التي نطبعها:
سودو AWK "BEGIN {FS =" "؛ طباعة "العضو \ ر \ tUID \ ر \ tGID \ ر \ ثوم \ ر \ tShell \ ن --------------". }
{طباعة $ 1، "\ ر \ ر"، $ 3، "\ ر \ ر"، $ 4، "\ ر \ ر"، $ 6، "\ ر \ ر"، $ 7؛}
END {طباعة "--------- \ nFile الكامل"} '  / الخ / باسود
العضو        UID دائرة المخابرات العامة     الرئيسية        شل 
-------------- 
الجذر          0    0      / الجذر       / بن / باش
الخفي        1    1      / البيرة / sbin   / بن / ش
بن           2    2      / بن        / بن / ش
تميز الكلية           3    3      / ​​ديف        / بن / ش
تزامن          4    65534  / بن        / بن / متزامنة
 .  .  . 
--------- 
ملف  كامل
بإمكاننا كما نرى تنسيق الأشياء بشكل أنيق من خلال الاستفادة من بعض ميّزات awk.
جميع الأقسام المُوسّعة اختياريّة، وفي الواقع القسم action الرئيسي بذاته اختياري إن تمّ تعريف قسم آخر، نستطيع أن نفعل أشياء من هذا القبيل كما يلي:
AWK "BEGIN {طباعة" يمكننا استخدام AWK مثل الأمر echo ". }
نحن يمكن استخدام AWK مثل الأمر echo

البحث في الحقول والتعابير المركبة في awk

قُمنا في أحد الأمثلة السّابقة بطباعة السّطر الذي يبدأ بـ "UUID" من الملف etc/fstab/، وكان هذا سهلًا لأنّنا كُنّا نبحث عن بداية السّطر بأكمله.
ولكن ماذا لو أردنا معرفة إذا ما كان نمط البحث قد وافق بداية الحقل field بدلًا من ذلك؟
نستطيع إنشاء الملف favorite_food.txt الذي يضم قائمة تحوي رقم العناصر والأطعمة المفضّلة لمجموعة من الأصدقاء:
صدى "ساندي 1 جزرة
2 الوسابي لوقا
3 شطيرة بريان
4 سلطة ريان
5 السباغيتي جيسيكا "  > favorite_food . TXT
إن كُنّا نريد إيجاد جميع الأطعمة التي تبدأ بـ “sa” من هذا الملف فبإمكاننا البدء بتجربة شيء مشابه لما يلي:
AWK '/ سا /' favorite_food . TXT
1 الجزر الرملية
 2 الوسابي لوقا
 3 شطيرة بريان
 4 سلطة ريان
قمنا هنا بالمطابقة مع أي مثال عن “sa” في الكلمة، وهذا لا يستثني كلمات مثل " wasabi" والتي تحوي هذا النمط في منتصفها، أو "sandy" غير الموجودة في العمود الذي نريده، فنحن مهتمون فقط بالكلمات التي تبدأ بـ “sa” والموجودة في العمود الثاني.
بإمكاننا إخبار awk أن يُطابِق بداية العمود الثاني باستخدام هذا الأمر:
AWK '$ 2 ~ / ^ سا /' favorite_food . TXT
3 شطيرة بريان
 4 سلطة ريان
يسمح لنا هذا كما نرى بالبحث فقط في بداية العمود الثاني عن مُطابِق.
يُخبِر الحرف "^" بأن يُحدِّد awk بحثه في بداية الحقل، ويُحدِّد الجزء "~field_num" بأنّه يجب فقط النّظر إلى العمود الثاني.
يُمكننا بسهولة البحث عن الأشياء غير المُطابِقة بتضمين الحرف "!" قبل المَدّة tilde (~).
سيعيد هذا الأمر جميع الأسطر التي لا تملك طعامًا يبدأ بـ “sa”:
AWK '$ 2! ~ / ^ سا /' favorite_food . TXT
1 الجزر الرملية
 2 الوسابي لوقا
 5 السباغيتي جيسيكا
إن قرّرنا لاحقًا أنّنا فقط مهتمّون بالأسطر التي يكون فيها ما سبق صحيحًا ورقم العنصر أقل من 5، فنستطيع استخدام تعبير مُركَّب مثل هذا:
AWK '$ 2! ~ / ^ سا / && $ 1 <5 " favorite_food . TXT
يُقدِّم لنا هذا بعض الأشياء الجديدة، أوّلها هو القدرة على إضافة مُتطلّبات إضافيّة للسطر الذي نريد مُطابقته باستخدام العامل operator &&، نستطيع باستخدام هذا جمع عدد كيفي من الشّروط للسطر الذي نريد مُطابقته.
نستخدم هذا العامل لإضافة التحقّق من أنّ قيمة العمود الأوّل أقل من 5.

الخاتمة

يجب أن يكون لدينا الآن فكرة أساسيّة حول كيفيّة قيام awk بالتعامل مع تنسيق، وطباعة الملفّات النّصيّة بانتقائيّة، رغم ذلك فإنّ awk موضوع أكبر من هذا بكثير، وهو في الواقع لغة برمجة كاملة تحتوي على إسناد للمتغيّرات، بُنى التّحكّم control structures، دوال مُضمَّنة built-in functions، والمزيد من ذلك، ويُمكن استخدامه في scripts لتنسيق النصوص بطريقة مقروءة بسهولة.
ولتعلّم المزيد حول كيفيّة العمل مع awk تحقّق من الموارد الكبيرة له على الإنترنت، واقرأ عن gawk وهو إصدار GNU من awk الموجود على توزيعات لينِكس الحديثة.
ترجمة -وبتصرف- ل كيفية استخدام لغة AWK إلى التلاعب النص في لينكس لصاحبه جوستين Ellingwood

=q =w =s =d =f =g =h =t =y =u =z =x =c =v =b =n =m =a =e =r عبّر عن تعليقكالإبتسامات