في نافذة الطباعة اختر «حفظ كملف PDF» كوجهة.
نظم التشغيل 1، الدرس العملي 12
كرر العمل بالحلقات while وuntil وfor، ثم ضعه في دوال تأخذ وسائط، وترجع حالة، وتحتفظ بمتغيراتها لنفسها.
for (( ))، والملفات، و"$@"break وcontinue، وقراءة ملف بالحلقة while read، وبناء قائمة خيارات (menu) بالأمر select$1 إليها، وإرسال حالة (status) بالأمر return وقيمة باستخدام $( )local، وما الذي تستطيع الدالة تغييره مع ذلك$?الجزء 1
التكرار ما دام الشرط صحيحا
ما دام الشرط صحيحا، استمر في تنفيذ الجسم
#!/bin/bash
# Basic while loop
counter=1
while [ $counter -le 10 ]
do
echo $counter
((counter++))
done
echo All donecounter=1 يضبط قيمة البداية[ ]، تماما كما في ifdo وdone((counter++)) يضيف 1، ثم يعود Bash إلى الشرطdoneتوقع خرج (output) while_loop.sh. ثم غير شرطه وحده إلى [ $counter -lt 10 ] وتوقع مرة أخرى.
$ bash while_loop.sh
1
2
3
4
5
6
7
8
9
10
All done$ bash while_lt.sh
1
2
3
4
5
6
7
8
9
All done#!/bin/bash
# Basic until loop
counter=1
until [ $counter -gt 10 ]
do
echo $counter
((counter++))
done
echo All donewhile نفسه، بالمعنى المعاكس1 إلى 10، ثم All done، تماما مثل while_loop.shمن مستند الأمثلة. توقع ما يطبعه.
#!/bin/bash
echo "Print the numbers which are even and divisible by 5"
counter=1
while [ $counter -le 20 ]
do
if [[ $counter%2 -eq 0 && $counter%5 -eq 0 ]]
then
echo "$counter"
fi
((counter++))
done
echo "Done"$ bash while.sh
Print the numbers which are even and divisible by 5
10
20
Doneيقول تعليقه إنه يطبع الأعداد الفردية. توقع أول عدد وآخر عدد.
#!/bin/bash
n=20
until [ $n -lt 0 ]
do
if [[ $n%2 -gt 0 ]]
then
echo $n
fi
((n=$n-1))
done$ bash until.sh
19
17
15
13
11
9
7
5
3
1الجزء 2
مرة واحدة لكل عنصر في قائمة
for var in list
do
commands
donevardo وdoneمن مستند الأمثلة. توقع سطري Tuesday وSunday.
#!/bin/bash
for day in Monday Tuesday Wednesday Thursday Friday Saturday Sunday
do
if [[ $day == 'Monday' || $day == 'Thursday' ]]
then
echo "Meeting on $day at 9:30 am"
elif [[ $day == 'Tuesday' || $day == 'Wednesday' || $day == 'Friday' ]]
then
echo "Training on $day at 11:00 am"
else
echo "$day is Holiday"
fi
done$ bash for.sh
Meeting on Monday at 9:30 am
Training on Tuesday at 11:00 am
Training on Wednesday at 11:00 am
Meeting on Thursday at 9:30 am
Training on Friday at 11:00 am
Saturday is Holiday
Sunday is Holidayالقائمة نفسها في متغير، مستخدمة بدون علامات التنصيص (quotes) ومعها. توقع الخرجين.
#!/bin/bash
planets='Mercury Venus Earth'
for planet in $planets
do
echo $planet
done
echo All done#!/bin/bash
planets='Mercury Venus Earth'
for planet in "$planets"
do
echo $planet
done
echo All done$ bash for_loop.sh
Mercury
Venus
Earth
All done$ bash for_quoted.sh
Mercury Venus Earth
All doneنقطتان تصنعان مدى؛ ونقطتان أخريان تضبطان الخطوة. توقع ما تطبعه كل حلقة.
for value in {1..5}
for value in { 1..5 }
for value in {10..0..2}| قائمة الحلقة | المطبوع فعلا، قيمة في كل سطر |
|---|---|
{1..5} | 1 2 3 4 5 |
{ 1..5 } (بمسافات في الداخل) | { 1..5 }: ثلاث كلمات، لا مدى |
{10..0..2} | 10 8 6 4 2 0: يعد تنازليا بخطوة 2 |
البداية والشرط والتغيير في سطر واحد
#!/bin/bash
for ((num = 1; num <= 5; num++))
do
echo $num
done
echo All donenum = 1 ينفذ مرة واحدة، قبل الحلقةnum <= 5 هو الشرط، ويختبر قبل كل تكرارnum++ ينفذ في نهاية كل تكرار$ bash for_loop_alternate_syntax.sh
1
2
3
4
5
All doneمحرف البدل (wildcard) يحول المجلد إلى قائمة
#!/bin/bash
# Make a php copy of any html files
for value in $1/*.html
do
cp $value $1/$( basename -s .html $value ).php
done$ ls site
about.html index.html
$ bash copy_html.sh site
$ ls site
about.html about.php index.html index.php$1/*.html: كل ملف .html في المجلد المعطى في $1basename -s .html site/about.html يطبع about$( ) يضع ذلك الاسم في الأمر cp: site/about.php"$@" هي قائمة كل وسائط (arguments) السكربت
#!/bin/bash
echo "Argument values are: $1 $2"
for arg in "$@"
do
key=$(echo $arg | cut -f1 -d=)
value=$(echo $arg | cut -f2 -d=)
case $key in
id) echo "Student ID = $value";;
mark) echo "Obtained mark = $value";;
*)
esac
done$ bash cl2.sh id=2026101 mark=90
Argument values are: id=2026101 mark=90
Student ID = 2026101
Obtained mark = 90id=2026101cut -f1 -d=: الجزء الذي قبل =؛ و-f2: الجزء الذي بعدهcase السطر الذي يطابق نمطهالجزء 3
break وcontinue وwhile read وselect
توقع أين يتوقف البحث.
#!/bin/bash
for value in {22..30}
do
if (( value % 7 == 0 ))
then
echo "found $value"
break
fi
echo "checked $value"
done
echo All done$ bash break_demo.sh
checked 22
checked 23
checked 24
checked 25
checked 26
checked 27
found 28
All doneأزيلت كل أذونات secret.txt (chmod 000). توقع الخرج.
#!/bin/bash
for value in $1/*
do
if [ ! -r $value ]
then
echo $value not readable 1>&2
continue
fi
cp $value backup/
echo "backed up $value"
done$ ls notes
a.txt b.txt secret.txt
$ bash copy_check.sh notes
backed up notes/a.txt
backed up notes/b.txt
notes/secret.txt not readable
$ ls backup
a.txt b.txtتوقع: لماذا تطبع الطريقة الأولى سطرا واحدا؟
echo "Reading file using cat command"
content=`cat hardware.txt`
echo $content
echo "Reading file line by line using loop"
while read line
do
echo $line
done < hardware.txt$ bash readfile.sh
Reading file using cat command
Monitor Keyboard Mouse Scanner Printer
Reading file line by line using loop
Monitor
Keyboard
Mouse
Scanner
PrinterPS3 هو المحث (prompt). توقع ما يطبعه الاختيار غير الصالح 5.
#!/bin/bash
planets='Mars Venus Earth Quit'
PS3='Select planet: '
select planet in $planets
do
if [ "$planet" == 'Quit' ]
then
break
fi
echo Hello $planet
done
echo Bye$ bash select_example.sh
1) Mars
2) Venus
3) Earth
4) Quit
Select planet: 2
Hello Venus
Select planet: 1
Hello Mars
Select planet: 5
Hello
Select planet: 4
Byeالجزء 4
اكتبها مرة واحدة، واستدعها باسمها
#!/bin/bash
# Basic function
print_something () {
echo Hello I am a function
}
print_something
print_something$ bash function_example.sh
Hello I am a function
Hello I am a functionname () { ... } أو function name { ... }() للزينة فقط: لا تضع بداخلها شيئا أبداتوقع سطري الخرج.
#!/bin/bash
# Calling a function before it is defined
print_something
print_something () {
echo Hello I am a function
}
print_something$ bash call_before.sh
call_before.sh: line 3: print_something: command not found
Hello I am a functionتكتب بعد الاسم؛ وتقرأ في الداخل بالأسماء $1، $2، ...
#!/bin/bash
# Passing arguments to a function
print_something () {
echo Hello $1
}
print_something Mars
print_something Jupiter$ bash arguments_example.sh
Hello Mars
Hello Jupiterprint_something Mars: قيمة $1 هي Mars$1 خاص بهلا تستطيع دوال Bash إرجاع قيمة، لكنها تستطيع ضبط حالة. توقع السطر الأخير.
#!/bin/bash
# Setting a return status for a function
print_something () {
echo Hello $1
return 5
}
print_something Mars
print_something Jupiter
echo The previous function has a return value of $?$ bash return_status_example.sh
Hello Mars
Hello Jupiter
The previous function has a return value of 5الدالة تطبع النتيجة؛ واستبدال الأوامر (command substitution) يلتقطها
#!/bin/bash
# Setting a return value to a function
lines_in_file () {
cat $1 | wc -l
}
num_lines=$( lines_in_file $1 )
echo The file $1 has $num_lines lines in it.$1$( ) يرسل ذلك النص إلى num_lines بدلا من الشاشة$( ) تطبع 3 على الشاشة ويبقى num_lines فارغا$ cat myfile.txt
Tomato
Lettuce
Capsicum
$ bash return_hack.sh myfile.txt
The file myfile.txt has 3 lines in it.توقع الأسطر الثلاثة.
#!/bin/bash
# Experimenting with variable scope
var_change () {
local var1='local 1'
echo Inside function: var1 is $var1 : var2 is $var2
var1='changed again'
var2='2 changed again'
}
var1='global 1'
var2='global 2'
echo Before function call: var1 is $var1 : var2 is $var2
var_change
echo After function call: var1 is $var1 : var2 is $var2Before function call: var1 is global 1 : var2 is global 2
Inside function: var1 is local 1 : var2 is global 2
After function call: var1 is global 1 : var2 is 2 changed again| السطر | var1 | var2 |
|---|---|---|
| قبل الاستدعاء | العام: global 1 | العام: global 2 |
| داخل الدالة | المحلي: local 1 | العام: global 2 |
| بعد الاستدعاء | العام، دون تغيير: global 1 | العام، وقد تغير داخل الدالة: 2 changed again |
رسالة، ونص يترك في متغير عام، ومساحة تحسب باستخدام bc
function print_message()
{
echo "Bash programming for beginner"
}
function ret_strdata()
{
return_str="Learn bash programming with functions"
}function calculate_area()
{
local radius=$1
area=$(echo $radius*$radius*3.14 | bc)
echo "Area of the circle is $area"
}print_message
ret_strdata
echo $return_str
echo "Enter the radius value"
read rad
calculate_area $rad$ bash func.sh
Bash programming for beginner
Learn bash programming with functions
Enter the radius value
4
Area of the circle is 50.24#!/bin/bash
# Create a wrapper around the command ls
ls () {
command ls -lh
}
ls$ bash override.sh
total 4.0K
-rwxr-xr-x 1 student student 85 Sep 25 09:00 override.shcommand ls يتجاوز الدالة وينفذ ls الحقيقيcommand تستدعي الدالة ls نفسها مرة بعد مرة: فلا يطبع شيءالجزء 5
رموز الخروج وأربع طرق لاستدعاء سكربت
توقع الإجابة للعدد 55 وللعدد 110.
#!/bin/bash
echo "Enter a numeric value"
read n
if [[ $n -le 100 ]]
then
exit 0
else
exit 1
fi#!/bin/bash
bash "first.sh"
if [ $? -eq 1 ]
then
echo "The input number is greater than 100"
else
echo "The input number is less than or equal to 100"
fi$ bash second.sh
Enter a numeric value
55
The input number is less than or equal to 100$ bash second.sh
Enter a numeric value
110
The input number is greater than 100من callpro.sh في مستند الأمثلة، بعد تشغيله فعلا
| الاستدعاء | ما يحدث |
|---|---|
source add.sh | يعمل داخل هذا السكربت: فيبقى متغيره result (100) مضبوطا بعد ذلك |
bash subtract.sh 50 20 | Bash جديد؛ يختفي متغيره result (30)، ويبقى متغيرنا 100 |
eval bash multiply.sh $a $b | يبني سطر الأمر (6، 7)، ثم ينفذه: 42 |
exec divide.sh 30 | يحل محل هذا السكربت: يطبع 15، ولا ينفذ أي سطر بعده |
الجزء 6
نحو 30 دقيقة: أجب على الورق، ثم شغل السكربت في ~/lab12
نحو 4 دقائق
#!/bin/bash
counter=10
until [ $counter -lt 4 ]
do
echo -n "$counter "
((counter-=3))
done
echo
for value in {15..3..4}
do
echo -n "$value "
done
echo$ bash p1.sh
10 7 4
15 11 7 3 نحو 5 دقائق
even_odd.sh: اطبع الأعداد من 1 إلى 10، عددا في كل سطرis even أو is odd1 is odd و2 is even#!/bin/bash
for n in {1..10}
do
if [[ $n%2 -eq 0 ]]
then
echo "$n is even"
else
echo "$n is odd"
fi
done$ bash even_odd.sh
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
10 is evenنحو 6 دقائق
grade: ضع $1 في متغير محلي اسمه mark؛ واطبع A للدرجة 85 على الأقل، وB للدرجة 65 على الأقل، وC في غير ذلك92 70 40 85$( ) في g واطبع mark 92 gets Agrade () {
local mark=$1
if [ $mark -ge 85 ]
then
echo A
elif [ $mark -ge 65 ]
then
echo B
else
echo C
fi
}for m in 92 70 40 85
do
g=$( grade $m )
echo "mark $m gets $g"
done$ bash grade.sh
mark 92 gets A
mark 70 gets B
mark 40 gets C
mark 85 gets Aنحو 4 دقائق
#!/bin/bash
count=0
add () {
local step=$1
count=$(( count + step ))
step=100
}
step=7
add 5
add 3
echo "count=$count step=$step"$ bash scope.sh
count=8 step=7count نسخة محلية: فيغير الاستدعاءان كلاهما المتغير العام، 0 + 5 = 5، ثم 5 + 3 = 8step محلي داخل add، ولذلك لا يغير step=100 إلا النسخة المحلية؛ ويبقى العام 7نحو 6 دقائق
valid: ترجع الحالة 0 للدرجة من 0 إلى 100، والحالة 1 في غير ذلك45 120 100 -3 واستدع valid لكل قيمة$? بعد كل استدعاء: اطبع 45 ok أو 120 invalidvalid () {
if [[ $1 -ge 0 && $1 -le 100 ]]
then
return 0
else
return 1
fi
}for m in 45 120 100 -3
do
valid $m
if [ $? -eq 0 ]
then
echo "$m ok"
else
echo "$m invalid"
fi
done$ bash valid.sh
45 ok
120 invalid
100 ok
-3 invalidنحو 5 دقائق
number_lines.sh: اقرأ hardware.txt بالحلقة while read1: MonitorTotal: 5 lines#!/bin/bash
n=0
while read line
do
((n++))
echo "$n: $line"
done < hardware.txt
echo "Total: $n lines"$ bash number_lines.sh
1: Monitor
2: Keyboard
3: Mouse
4: Scanner
5: Printer
Total: 5 lineswhile تعمل ما دام شرطها صحيحا، وuntil حتى يصبح صحيحا؛ وافحص التكرار الأول والأخيرfor تأخذ عنصرا واحدا في كل تكرار: كلمات، أو متغيرا بعلامات تنصيص أو بدونها، أو مدى بخطوة، أو ملفات، أو "$@"break تغادر الحلقة، وcontinue تتخطى تكرارا واحدا، وwhile read تقرأ ملفا سطرا بسطر$1، $2، ...return تضبط حالة في $?؛ واطبع القيمة والتقطها باستخدام $( )local، وإلا غيرت الدالة المتغيرات العامةMahmoud Abas|برمجة Bash، الجزء 2: الحلقات والدوال