اختبار: إتقان Bash و Shell
هل تستطيع التحدث مع الحواسيب؟ أعني، بطلاقة؟
اختبر مهاراتك في كتابة نصوص Bash مع هذه الأسئلة الـ16!
تغطي المتغيرات، الحلقات، الشروط، معالجة النصوص، الدوال، والمزالق النحوية من الأساسية إلى الصعبة.
صقل (أو إثبات) مهاراتك في كتابة نصوص الصدفة!
كيف يتم تعريف المتغيرات في Bash؟
يتم إعلان المتغيرات في Bash بدون مسافات حول علامة =. على سبيل المثال:
name=Aliceهذا يعين القيمة "Alice" للمتغير name.
ملاحظة: $name يُستخدم للإشارة أو قراءة قيمة المتغير.
إضافة مسافات تجعل الصدفة تفسر الأمر كبرنامج لتشغيله، وهو ليس ما تريده عند تعيين متغير.
أيضًا، Bash حساس لحالة الأحرف، لذا name و NAME و Name متغيرات مختلفة.
أخيرًا، لا يمكن أن تحتوي أسماء المتغيرات على مسافات أو شرطات (-). استخدم الشرطات السفلية (_) أو camelCase بدلاً من ذلك.
ما الذي سيطبع It's 🔨 Time!؟
أعرف. من الجنون كيف يجعل الإفلات تحليل السلاسل النصية صعبًا بسرعة. تخيل إفلات لغات أخرى في سلاسل Bash - مع كل تلك علامات الاقتباس والفواصل العليا ورموز $ التي قد تزعجك. 🫠
علامات الاقتباس المفردة تحتاج إلى إفلات داخل السلاسل المقتبسة بمفردها. التسلسل (إغلاق الاقتباس، إفلات الاقتباس، إعادة فتح الاقتباس) ('\'') يسمح بإخراج:
It's 🔨 Time!هناك طرق أخرى للتعامل مع هذا، لكن هذه هي الأكثر شيوعًا.
ماذا سيكون ناتج هذا الأمر؟
echo c{a,b}tتوليد التوسيع بالأقواس {} نسخًا متعددة من سياق السلسلة النصية، واحدة (أو أكثر) لكل قيمة أو نمط مفصول بفاصلة.
هنا، c{a,b}t يتوسع إلى:
cat cbtالآن، ماذا سيطبع هذا؟
price="$100"echo "Cost: $price"المتغيرات المرقمة لها معنى خاص. في هذه الحالة، $1 هو متغير خاص يحمل الوسيط الأول الذي تم تمريره إلى السكريبت أو الدالة.
بما أننا نشغل السكريبت في بيئة REPL، فلا توجد وسائط، لذا فإن $1 فارغ. النص المتبقي 00 يُطبع كما هو.
لطباعة حرف $ حرفيًا، استخدم علامات الاقتباس المفردة، أو قم بإفلاته باستخدام الخط المائل العكسي (\):
price="\$100"echo "Cost: $price"ماذا يحدث هنا؟
str="Bark bark"echo ${str/bark/meow}بناء الجملة ${var/pattern/replacement} يستبدل أول ظهور لـ pattern بـ replacement. هنا، الناتج هو:
Bark meowإنها حساسة لحالة الأحرف. للتعامل مع كل من bark و Bark، استخدم نمطًا مثل ${var/[Bb]ark/Bark} أو قم بتطبيع السلسلة قبل الاستبدال.
لاستبدال جميع الظهورات، استخدم ${var//pattern/replacement}.
للاستبدال من بداية السلسلة، استخدم ${var/#pattern/replacement}.
للاستبدال من نهاية السلسلة، استخدم ${var/%pattern/replacement}.
كيف يمكنك الحصول على طول متغير في Bash؟
الصيغة ${#username} تُرجع طول username.
على سبيل المثال:
username="@justsml"echo ${#username} # => 8بينما wc قد تعمل، إلا أنها تقنيًا ليست جزءًا من Bash.
الأداة wc هي نكتة داخلية قديمة تشير إلى “water closet”، أو المرحاض.
أمزح! هل يقرأ أحد هذه النصوص؟
في الواقع wc هي أمر قديم من Posix (وأيام AT&T Unix.) وهي اختصار لـ “word count” ويمكنها عد الأسطر والكلمات والأحرف في ملف أو تيار إدخال.
ماذا يخرج هذا السكريبت إذا كان الملف cats.txt موجودًا؟
if [ -e cats.txt]; then echo "File exists"else echo "File does not exist"fiهل لاحظت المسافة المفقودة قبل القوس الإغلاق؟
Bash حساس جدًا هنا: المسافات مطلوبة داخل تعبيرات الأقواس.
بسبب المسافة المفقودة، يرى الأمر [ عدم وجود قوس إغلاق ]، فيطبع Bash رسالة تشخيص، ويعتبر الاختبار فاشلاً، ويستمر إلى فرع else.
الصيغة الصحيحة هي:
if [ -e example.txt ]; then echo "File exists"else echo "File does not exist"fiملاحظة: الأقواس المزدوجة [[ ]] موصى بها للتعبيرات الشرطية. انظر BashFAQ.
كيف يمكننا مقارنة السلاسل النصية في Bash؟
cat1="Rosie"cat2="Sunflower"if [ "$cat1" === "$cat2" ]; then echo "Same cat"else echo "Different cats"fiخطأ آخر في بناء الجملة الاختباري!
هل لاحظت العامل غير الصحيح ===؟
ربما كنت تفكر في JavaScript…
مع [ ... ]، يبلغ Bash عن تشخيص ويكون الشرط خاطئًا، لذا يطبع فرع else Different cats. في Bash، استخدم = أو == لمقارنات المساواة.
ماذا سيكون مخرجات هذا السكريبت؟
function greet () { echo "$1"}greet Hi Danالدوال في Bash يمكنها استقبال الوسائط. المتغير $1 يحمل أول وسيطة تم تمريرها إلى الدالة.
تذكر، $0 هو اسم السكريبت، $1 هي الوسيطة الأولى، $2 هي الثانية، وهكذا. المسافات تفصل بين الوسائط. لذا، greet Hi Dan تمرر "Hi" كأول وسيطة. لتمرير "Hi Dan" كوسيطة واحدة، يجب وضعها بين علامتي اقتباس: greet "Hi Dan".
كيف تعمل العمليات الحسابية في Bash؟
بناء الجملة (( )) يقوم بإجراء العمليات الحسابية على الأعداد الصحيحة في Bash.
يمكن استخدامه في العمليات الحسابية البسيطة:
((result = 2 + 2))echo $result # => 4أو للتعبيرات الشرطية:
if (( 2 > 1 )); then echo "2 is greater than 1"fiللعمليات الحسابية على الأعداد العشرية، فكر في استخدام bc أو awk.
ماذا يفعل : في هذا السكريبت؟
rosie="Bad cat, good cat"echo ${rosie:9}الصيغة ${var:offset} تستخرج سلسلة فرعية تبدأ من offset. هنا، المخرجات هي:
good catلاستخراج سلسلة فرعية بطول محدد، استخدم ${var:offset:length}.
للاستخراج من نهاية السلسلة، استخدم ${var: -offset}. (لاحظ المسافة قبل -!)
أي خيار سينفذ الأمر ls -l ويعيد المخرجات؟
بناء $(ls -l) ينفذ الأمر داخل الأقواس ويستبدل المخرجات. على سبيل المثال:
echo "Today is $(date +%F)"# => Today is 2029-12-31الخيار الأول يستخدم علامات الاقتباس المفردة '، وليس علامات التنصيص الخلفية. هذا يمنع التوسيع، لذا '$(date +%F)' سيطبع ببساطة السلسلة الحرفية $(date +%F).
بينما لا يزال استخدام علامات التنصيص الخلفية (`ls -l`) مدعومًا لتنفيذ الأوامر، إلا أنه أصبح مؤخرًا نوعًا ما نمطًا مضادًا (في بعض السياقات.) يوصي معظمهم باستخدام $(command) لتحسين قابلية القراءة والاتساق مع مختلف الصدف والإصدارات.
الأقواس المعقوفة ${} تُستخدم لتوسيع المتغيرات، وليس لاستبدال الأوامر.
الحرف % لا يُستخدم لاستبدال الأوامر.
أي عامل يستخدم لدمج مخرجات الخطأ مع المخرجات القياسية؟
يقوم العامل 2>&1 بتوجيه الخطأ القياسي (وصف الملف 2) إلى المخرجات القياسية (وصف الملف 1). هذا مفيد لالتقاط رسائل الخطأ في نفس تيار المخرجات مثل المخرجات العادية.
العامل 1>&2 يقوم بتوجيه المخرجات القياسية إلى الخطأ القياسي، لكن السؤال كان عن كيفية توجيه الخطأ القياسي إلى المخرجات القياسية.
لمعرفة المزيد عن ما يحدث تحت الغطاء، اطّلع على دليل إعادة التوجيه الممتاز لجريج.
أيضًا، شكرًا لمستخدم Reddit u/OneTurnMore على اقتراح تحسينات النص.
هل تركك اختبار Bash الخاص بي في حالة من الفوضى؟
أخبرني في التعليقات أدناه!
قراءة إضافية
حسّن مهاراتك في Bash باستخدام الموارد التالية:
- دليل Bash
- أسئلة شائعة عن Bash
- ShellCheck
- أكاديمية Bash
- درس تعليمي لبرمجة Bash
- دليل Bash المرجعي
- ويكي Bash Hackers
- دليل Bash للمبتدئين
- بطاقة Bash المرجعية