DanLevy.net

اختبار: إتقان Bash و Shell

هل تستطيع التحدث مع الحواسيب؟ أعني، بطلاقة؟

اختبر مهاراتك في كتابة نصوص Bash مع هذه الأسئلة الـ16!

تغطي المتغيرات، الحلقات، الشروط، معالجة النصوص، الدوال، والمزالق النحوية من الأساسية إلى الصعبة.

صقل (أو إثبات) مهاراتك في كتابة نصوص الصدفة!

كيف يتم تعريف المتغيرات في Bash؟

يتم إعلان المتغيرات في Bash بدون مسافات حول علامة =. على سبيل المثال:

Terminal window
name=Alice

هذا يعين القيمة "Alice" للمتغير name.

ملاحظة: $name يُستخدم للإشارة أو قراءة قيمة المتغير.

إضافة مسافات تجعل الصدفة تفسر الأمر كبرنامج لتشغيله، وهو ليس ما تريده عند تعيين متغير.

أيضًا، Bash حساس لحالة الأحرف، لذا name و NAME و Name متغيرات مختلفة.

أخيرًا، لا يمكن أن تحتوي أسماء المتغيرات على مسافات أو شرطات (-). استخدم الشرطات السفلية (_) أو camelCase بدلاً من ذلك.

ما الذي سيطبع It's 🔨 Time!؟

أعرف. من الجنون كيف يجعل الإفلات تحليل السلاسل النصية صعبًا بسرعة. تخيل إفلات لغات أخرى في سلاسل Bash - مع كل تلك علامات الاقتباس والفواصل العليا ورموز $ التي قد تزعجك. 🫠

علامات الاقتباس المفردة تحتاج إلى إفلات داخل السلاسل المقتبسة بمفردها. التسلسل (إغلاق الاقتباس، إفلات الاقتباس، إعادة فتح الاقتباس) ('\'') يسمح بإخراج:

It's 🔨 Time!

هناك طرق أخرى للتعامل مع هذا، لكن هذه هي الأكثر شيوعًا.

ماذا سيكون ناتج هذا الأمر؟

Terminal window
echo c{a,b}t

توليد التوسيع بالأقواس {} نسخًا متعددة من سياق السلسلة النصية، واحدة (أو أكثر) لكل قيمة أو نمط مفصول بفاصلة.

هنا، c{a,b}t يتوسع إلى:

cat cbt

الآن، ماذا سيطبع هذا؟

Terminal window
price="$100"
echo "Cost: $price"

المتغيرات المرقمة لها معنى خاص. في هذه الحالة، $1 هو متغير خاص يحمل الوسيط الأول الذي تم تمريره إلى السكريبت أو الدالة.

بما أننا نشغل السكريبت في بيئة REPL، فلا توجد وسائط، لذا فإن $1 فارغ. النص المتبقي 00 يُطبع كما هو.

لطباعة حرف $ حرفيًا، استخدم علامات الاقتباس المفردة، أو قم بإفلاته باستخدام الخط المائل العكسي (\):

Terminal window
price="\$100"
echo "Cost: $price"

ماذا يحدث هنا؟

Terminal window
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.

على سبيل المثال:

Terminal window
username="@justsml"
echo ${#username} # => 8

بينما wc قد تعمل، إلا أنها تقنيًا ليست جزءًا من Bash.

الأداة wc هي نكتة داخلية قديمة تشير إلى “water closet”، أو المرحاض. أمزح! هل يقرأ أحد هذه النصوص؟

في الواقع wc هي أمر قديم من Posix (وأيام AT&T Unix.) وهي اختصار لـ “word count” ويمكنها عد الأسطر والكلمات والأحرف في ملف أو تيار إدخال.

ماذا يخرج هذا السكريبت إذا كان الملف cats.txt موجودًا؟

Terminal window
if [ -e cats.txt]; then
echo "File exists"
else
echo "File does not exist"
fi

هل لاحظت المسافة المفقودة قبل القوس الإغلاق؟

Bash حساس جدًا هنا: المسافات مطلوبة داخل تعبيرات الأقواس.

بسبب المسافة المفقودة، يرى الأمر [ عدم وجود قوس إغلاق ]، فيطبع Bash رسالة تشخيص، ويعتبر الاختبار فاشلاً، ويستمر إلى فرع else.

الصيغة الصحيحة هي:

Terminal window
if [ -e example.txt ]; then
echo "File exists"
else
echo "File does not exist"
fi

ملاحظة: الأقواس المزدوجة [[ ]] موصى بها للتعبيرات الشرطية. انظر BashFAQ.

كيف يمكننا مقارنة السلاسل النصية في Bash؟

Terminal window
cat1="Rosie"
cat2="Sunflower"
if [ "$cat1" === "$cat2" ]; then
echo "Same cat"
else
echo "Different cats"
fi

خطأ آخر في بناء الجملة الاختباري!

هل لاحظت العامل غير الصحيح ===؟

ربما كنت تفكر في JavaScript…

مع [ ... ]، يبلغ Bash عن تشخيص ويكون الشرط خاطئًا، لذا يطبع فرع else Different cats. في Bash، استخدم = أو == لمقارنات المساواة.

ماذا سيكون مخرجات هذا السكريبت؟

Terminal window
function greet () {
echo "$1"
}
greet Hi Dan

الدوال في Bash يمكنها استقبال الوسائط. المتغير $1 يحمل أول وسيطة تم تمريرها إلى الدالة.

تذكر، $0 هو اسم السكريبت، $1 هي الوسيطة الأولى، $2 هي الثانية، وهكذا. المسافات تفصل بين الوسائط. لذا، greet Hi Dan تمرر "Hi" كأول وسيطة. لتمرير "Hi Dan" كوسيطة واحدة، يجب وضعها بين علامتي اقتباس: greet "Hi Dan".

أي عامل يربط مخرجات أمر ما بـ مدخلات الأمر التالي؟

عامل الأنبوب | يربط مخرجات أمر ما بمدخلات أمر آخر. على سبيل المثال:

Terminal window
echo "Mr. Levy 👨🏻‍🔬" | wc -m
# => 14

كيف تعمل العمليات الحسابية في Bash؟

بناء الجملة (( )) يقوم بإجراء العمليات الحسابية على الأعداد الصحيحة في Bash.

يمكن استخدامه في العمليات الحسابية البسيطة:

Terminal window
((result = 2 + 2))
echo $result # => 4

أو للتعبيرات الشرطية:

Terminal window
if (( 2 > 1 )); then
echo "2 is greater than 1"
fi

للعمليات الحسابية على الأعداد العشرية، فكر في استخدام bc أو awk.

أي من هذه الخيارات يقوم بضرب 10 و 0.5 بشكل صحيح، ويطبع 5؟

بناء الجملة (( )) يقوم فقط بالحساب الصحيح (الأعداد الصحيحة) بدون أعداد عشرية!

قد تفتقر Bash (بشكل مفاجئ) إلى دعم مدمج للحساب بالأعداد العشرية.

الحل الأكثر شيوعًا هو استخدام أدوات GNU bc أو awk.

ماذا يفعل : في هذا السكريبت؟

Terminal window
rosie="Bad cat, good cat"
echo ${rosie:9}

الصيغة ${var:offset} تستخرج سلسلة فرعية تبدأ من offset. هنا، المخرجات هي:

good cat

لاستخراج سلسلة فرعية بطول محدد، استخدم ${var:offset:length}.

للاستخراج من نهاية السلسلة، استخدم ${var: -offset}. (لاحظ المسافة قبل -!)

ما هي الكلمة التي ليست ❌ من كلمات الحلقات في Bash؟

each ليست كلمة حلقة في Bash. كلمات الحلقات الرئيسية هي for و while و until.

بينما do ليست تقنيًا كلمة حلقة، إلا أنها جزء أساسي من بناء جملة الحلقات.

أي خيار سينفذ الأمر ls -l ويعيد المخرجات؟

بناء $(ls -l) ينفذ الأمر داخل الأقواس ويستبدل المخرجات. على سبيل المثال:

Terminal window
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 باستخدام الموارد التالية: