We are still cooking the magic in the way!
معالجة النصوص: grep وsed وawk
معالجة النصوص: grep وsed وawk
في بيئة الإنتاج، النصوص الخام في كل مكان — سجلات التطبيقات التي تحتوي على آلاف الأسطر، وسجلات وصول nginx التي تنمو بعشرات الآلاف من الطلبات في الدقيقة، وملفات CSV المُصدَّرة من أنظمة المراقبة، وملفات الإعدادات الممتدة عبر مئات الخوادم. القدرة على البحث والاستخراج والتحويل والتلخيص لهذا النص من سطر الأوامر — دون كتابة سكريبت Python، دون فتح ملف في محرر، دون انتظار تحديث لوحة تحكم — تُعدّ من أعلى المهارات المردودية لمهندس DevOps. ثلاث أدوات تتولى العمل الشاق: grep وsed وawk. لكل أداة غرض متميز، وتتكامل الثلاثة بسلاسة عبر الأنابيب (pipes).
grep يختار الأسطر. sed يحوّل النص (استبدال وحذف على مستوى الحروف). awk يحسب على الحقول المُهيكَلة (عمليات حسابية، شروط، تجميعات). عند الشك، استخدم الأداة الأضعف التي تحل المشكلة — سطر أوامر grep أسرع في الكتابة والتنفيذ وأسهل في القراءة لمن يأتي بعدك.
grep — البحث في النصوص على نطاق واسع
يطبع grep كل سطر من المدخلات يطابق نمطًا معينًا. اسمه مشتق من أمر المحرر ed وهو g/re/p (مطابقة عالمية لتعبير نظامي وطباعته). لغة النمط الافتراضية هي التعبيرات النظامية الأساسية (BRE)؛ العلَم -E يُفعّل التعبيرات النظامية الموسّعة (ERE)، و-P يُفعّل التعبيرات النظامية المتوافقة مع Perl (PCRE) على الأنظمة التي تدعمها.
الأعلام التي ستستخدمها يوميًا في الإنتاج:
-i— مطابقة غير حساسة لحالة الأحرف-v— عكس المطابقة (طباعة الأسطر التي لا تطابق)-r/-R— بحث متكرر في المجلدات-l— طباعة أسماء الملفات فقط التي تحتوي على تطابق-n— إضافة رقم السطر قبل كل سطر في المخرجات-c— طباعة عدد الأسطر المتطابقة لكل ملف-A N/-B N/-C N— طباعة N سطرًا بعد / قبل / حول كل تطابق (السياق)-o— طباعة الجزء المتطابق فقط من السطر وليس السطر بأكمله-E— تعبيرات نظامية موسّعة (التبديل|، المحددات الكمية+،?، التجميع())--color=auto— تمييز التطابقات بالألوان (اضبطه في ملف تعريف shell لديك)
grep -F للسلاسل الحرفية: عندما يحتوي نمط البحث على حروف خاصة في التعبيرات النظامية (.، *، [، $)، استخدم grep -F (سلسلة ثابتة) لتخطي تفسير التعبيرات النظامية كليًا. البحث عن 10.0.1.5 بـ grep العادي يطابق أي حرف في مواضع النقاط. grep -F "10.0.1.5" يطابق السلسلة الحرفية بالضبط. هذا مهم عند البحث في السجلات عن عناوين IP أو أسماء فئات تتبع المكدس أو أي سلسلة تبدو كتعبير نظامي.
sed — تحرير الدفق للتحويل
sed (محرر الدفق) يقرأ المدخلات سطرًا بسطر، ويُطبّق برنامج أوامر تحرير، ويكتب إلى المخرجات القياسية. لا يعدّل الملفات في مكانها أبدًا ما لم تمرر -i. أمر sed الأكثر استخدامًا هو s/نمط/استبدال/أعلام — الاستبدال. فهم sed يعني فهم هذا الأمر الواحد بعمق.
أعلام الاستبدال المهمة:
g— استبدال جميع التكرارات في السطر (وليس الأول فقط)i— مطابقة غير حساسة لحالة الأحرف (GNU sed)p— طباعة السطر بعد الاستبدال (مفيد مع-nلطباعة الأسطر المعدّلة فقط)2،3— استبدال التكرار رقم N فقط في السطر
sed -i بين GNU وBSD: على Linux، sed -i '' يفشل (السلسلة الفارغة بعد -i تُعامَل كوسيط التالي). على macOS (BSD sed)، sed -i '' هو التعديل الصحيح في المكان دون نسخة احتياطية. لكتابة سكريبتات محمولة، استخدم sed -i.bak (ينشئ دائمًا نسخة احتياطية) أو استخدم perl -pi -e بدلًا من ذلك، الذي يتصرف باتساق. في Dockerfiles وخطوط CI التي تستهدف حاويات Linux، نادرًا ما تواجه هذا الفرق، لكنه سيصطادك حتمًا حين يشغّل أحد زملائك سكريبتك على Mac.
awk — معالجة البيانات الموجّهة بالحقول
awk لغة برمجة كاملة مصمّمة حول مفهوم السجلات والحقول. بشكل افتراضي، تقسّم كل سطر مدخلات (سجل) على المسافات البيضاء إلى حقول ($1، $2، ...، $NF للحقل الأخير، $0 للسطر بأكمله). تُنفّذ برنامج نمط-إجراء على كل سجل. الشكل المعياري هو awk '/نمط/ { إجراء }'.
المتغيرات المدمجة التي تظهر باستمرار في السكريبتات الحقيقية:
NR— رقم السطر (السجل) الحالي عبر جميع الملفاتNF— عدد الحقول في السجل الحاليFS— فاصل الحقول (الافتراضي: مسافات بيضاء؛ يُضبط بـ-F)OFS— فاصل حقول المخرجات (الافتراضي: مسافة)$0— السطر الحالي بأكمله$1...$NF— الحقول الفرديةBEGIN { }— يُنفَّذ مرة واحدة قبل قراءة أي مدخلاتEND { }— يُنفَّذ مرة واحدة بعد استهلاك جميع المدخلات
تأليف الأدوات الثلاث: خطوط أنابيب للعالم الحقيقي
القوة الحقيقية لهذه الأدوات تظهر عند تركيبها معًا عبر الأنابيب. كل أداة في السلسلة متخصصة تُتقن شيئًا واحدًا بامتياز. تقرأ السلسلة من اليسار إلى اليمين كسرد لمعالجة البيانات.
اعتبارات الأداء على نطاق واسع
عند معالجة ملفات سجل بحجم جيجابايتات — وهو أمر شائع في الإنتاج — فإن اختيار الأداة وترتيبها له تأثيرات أداء حقيقية:
- ضع
grepأولًا في خط الأنابيب. يرفض الأسطر مبكرًا، مما يقلل البيانات التي يجب علىsedوawkمعالجتها. تصفية 100 مليون سطر إلى 10,000 سطر قبل تسليمها لـawkأسرع بمراتب من تغذية كل الـ 100 مليون لـawk. - استخدم
grep -Fللسلاسل الثابتة. مطابقة التعبيرات النظامية لها تكلفة؛ مطابقة السلاسل البسيطة (خوارزمية Boyer-Moore) أسرع بشكل ملحوظ عندما لا تحتاج تعبيرات نظامية. - فضّل
awkعلى حلقة shell لعمليات الأعمدة الحسابية. حلقة shell تعالج سطرًا واحدًا لكل تكرار وتُفرز عملية فرعية لكل سطر؛awkيعالج ملايين الأسطر في استدعاء عملية واحدة. - بالنسبة للملفات الكبيرة جدًا، فكّر في
LC_ALL=C. الإضافة البادئةLC_ALL=Cتُعطّل معالجة الحروف متعددة البايت ويمكن أن تجعلgrepوawkأسرع بمعدل 3-5 أضعاف على السجلات ذات السيادة ASCII.
scripts/. خطوط الأنابيب التي تعيش في تاريخ شِلك فقط هي معرفة تشغيلية تختفي عندما تغادر الفريق. وثّق صيغة المدخلات والمخرجات المتوقعة والتبعيات الخارجية في أعلى الملف.
أنماط الفشل الشائعة
grepيُعيد كود خروج 1 (لا تطابق) ويوقف خط أنابيب معset -e. في السكريبتات التي تستخدمset -e،grepالذي لا يجد شيئًا يخرج بكود 1، مما يُجهض السكريبت. احمِ نفسك بـgrep ... || trueعندما تكون نتيجة الصفر تطابقات مقبولة.- sed في المكان على رابط رمزي يتبع الرابط وليس الرابط نفسه. عندما يكون ملف الإعداد رابطًا رمزيًا (شائع في البيئات المُدارة بـ Ansible)،
sed -iيستبدل هدف الرابط. تحقق من النتيجة بـls -laبعد التعديل. - ترقيم حقول awk يبدأ من 1 وليس 0.
$0هو السطر بأكمله؛$1هو الحقل الأول. المهندسون القادمون من Python أو Go يُسنّدون رقم الحقل الخاطئ ويحصلون بصمت على مخرجات غير صحيحة — دائمًا تحقق بعينة صغيرة أولًا. - التعبيرات النظامية الحساسة للإعداد المحلي في awk. فئات الحروف مثل
[[:alpha:]]تطابق بشكل مختلف حسب الإعداد المحلي. اضبطLC_ALL=Cللمطابقة المتوقعة المقتصرة على ASCII في سكريبتات الإنتاج.
مع grep وsed وawk في صندوق أدواتك — وفهم كيفية تأليفها — يمكنك الإجابة في ثوانٍ على أسئلة كانت تتطلب كتابة سكريبت Python أو تحميل البيانات في قاعدة بيانات أو انتظار تحديث لوحة تحكم BI. على نطاق واسع، تلك السرعة هي الفرق بين حادثة تستمر 10 دقائق وتشخيص يستغرق 10 ثوانٍ.