ผู้เขียน/โดย : เกริก ภิรมย์โสภา (Krerk Piromsopa)
เขียนเมื่อ/ปรับปรุง : 2004-07-14 16:56:02
เอกสารนี้จัดทำขึ้นเพื่อแนะนำ และใช้สำหรับการอ้างอิงให้กับผู้ที่จะเขียนโปรแกรมบน
Shell โดยจะกล่าวถึงโครงสร้างโดยทั่วไปของ Shell แสดงการใช้คำสั่งต่างๆ
พร้อมตัวอย่างประกอบ ทั้งนี้ตัวอย่างดังกล่าวจะเปรียบเทียบระหว่าง bash
, ksh และ tcsh เป็นหลัก โดยข้อมูลในเอกสารนี้จะเน้นเพียงข้อมูลที่เป็นมาตรฐานของ
Shell ทั่วไปเท่านั้น เนื่องจากในปัจจุบัน Shell หมายๆ ตัวได้มีการปรับปรุงให้ทำงานได้กว้างมากขึ้น
และ เขียนง่ายยิ่งขึ้นเช่น bash บน Linux ซึ่งจะรวมความสามารถของ ksh และ
tcsh หลายอย่างไว้ด้วยกัน เป็นต้น
ลักษณะทั่วไปของ Shell
หน้าที่พื้นฐานของ Shell โดยทั่วไปนั้นคือการรับคำสั่งจาก
User เพื่อทำการบอก OS ให้ Load และ Run Program ต่างๆ อย่างไรก็ตามได้มีการพัฒนาให้
Shell มีความสามารถในการประมวลผลคำสั่งต่างๆ เพื่อให้ทำงานในลักษณะของ
Batch ได้ ทั้งนี้โครงสร้างของโปรแกรมต่างๆ หรือ Shell นั้นจะประกอบด้วยตัวแปรระบบ
หรือ สภาวะแวดล้อม(Envirenment) ซึ่งพร้อมที่จะส่งให้โปรแกรมอื่นๆ ประมวลผลต่อ
ประโยคเงื่อนไขต่างๆ ระบบ Profile สำหรับวัดเวลาในการประมวลผลของโปรแกรมต่างๆ
และ User Defined Function
ในการวัดเวลาที่ใช้ในการทำงานคำสั่งต่างๆ ของ Unix นั้นสามารถทำได้โดยใส่
time นำหน้าคำสั่งที่ต้องการประมวลผล ซึ่งโปรแกรมจะบอก OS ให้ทำการจับเวลา
และ รายงานผลเวลาที่ใช้ในการประมวลผลหลังจากทำงานเสร็จ เช่น
time ls -al /bin/*
สำหรับกรณี Shell บน Unix นั้น การเขียนคำสั่งแต่ละคำสั่งจะต้องจบคำสั่ง
ด้วยบรรทัดใหม่ หรือ เครื่องหมาย semi-colon เสมอ “;” และกรณีที่คำสั่งมีความยาวมาก
(ไม่จบภายใน 1 บรรทัด) ให้จบบรรทัดด้วยเครื่องหมาย “” แล้วพิมพ์ต่อในบรรทัดถัดไป
เช่น
echo “Test”; ls;
echo “Hello
world”
การเขียน Comment ใน Shell Script จะใช้เครื่องหมาย “#”
ทั้งนี้ในการเขียนโปรแกรมที่เป็นภาษา Script ต่างๆ บน Unix
นั้น ในบรรทัดแรกเราควรจะระบุชื่อโปรแกรมที่จะทำการประมวลผล Script นั้นๆ
ไว้ด้วยเช่น
#! /bin/ksh
หรือ กรณีเป็น Perl อาจจะเขียนเป็น
#! /usr/bin/perl
เป็นต้น
การใช้งาน Variable / Environment
บนระบบ OS โดยทั่วไปมักจะมี Environment
หรือ System Variable เพื่อส่งผ่านค่าระหว่างโปรแกรมต่างๆ ภายในระบบ เสมอ
ซึ่งโดยทั่วไปเราจะอ่านค่า Environment (ของ OS เกือบทุกตัว) ได้โดยการใช้คำสั่ง
set
ตัวอย่างการตั้งค่า Variable ใน Shell เช่น
| bash / ksh | tcsh |
| myname=”Krerk Piromsopa”count=5; | set myname=”Krerk Piromsopa”set count=5; |
นอกจากนี้เรายังสามารถนำผลลัพธ์จากการ Run Programm อื่นๆ
มาเป็นค่า Variable ได้อีกด้วย โดยใช้ Back Quote แทน หรือ Run คำสั่งภายในเครื่องหมาย
$(command) เช่น
| bash / ksh | tcsh |
| list = `ls`# หรือ list=$(ls) |
set list = `ls`# หรือ
set list=$(ls) |
ทั้งนี้หากต้องการให้ค่า Variable หรือ Environment คงอยู่หลังจากที่
Run Shell สามารถทำได้โดยการ export เช่น
export myname,count
นอกจากนี้ยังมีตัวแปรระบบที่จะใช้สำหรับการอ้างอิงในโปรแกรม
Shell ได้อีกด้วย เช่น
| ตัวแปร | ความหมาย |
| $# | แสดงจำนวน Parameter ที่ส่งมาให้กับระบบ |
| $? | เก็บค่าที่ได้จากประมวลผลคำสั่งก่อนหน้านี้ |
| $0 | แสดงชื่อของ โปรแกรมที่กำลังประมวลผลอยู่ |
| $* | เก็บค่า Parameter ทุกตัวที่ใช้ในการประมวลผล ($1 $2 ….) |
| “$@” | เก็บค่า Parameter ทุกตัวที่ใช้ในการประมวลผล (“$1″ “$2″ ….) |
การใช้งาน Variable ทุกตัวนั้นจะเป็น Implicit Declaration
กล่างคือผู้ใช้ไม่จำเป็นต้องประกาศตัวแปร เช่นในภาษา C หรือ ภาษาชั้นสูงอื่นๆ
และ เมื่อต้องการยกเลิกตัวแปรนั้นสามารถทำได้โดยใช้คำสั่ง unset varname
เช่น
unset myname
test และ expression
บน bash และ ksh จะมีคำสั่ง Test และการเขียนเงื่อนไขในการตรวจสอบ
Expression ต่างๆ ในการเขียนประโยคเงื่อนไขต่าง ซึ่งมีโครงสร้างการเขียนดังนี้
test expression
หรือ
[ expression ]
สำหรับ tcsh นั้นจะไม่มีคำสั้ง test แต่จะมีการนำ
expression เพื่อไปใช้ในการประมวผลผลคำสั่งต่างๆ เช่นกัน
ทั้งนี้ expression บน bash กับ ksh และ
tcsh นั้นจะมีโครงสร้างที่แตกต่างกัน ดังอธิบายได้ดังต่อไปนี้
| bash / ksh | tcsh | ความหมาย |
| คำสั่งเกี่ยวกับจำนวนเต็ม | ||
| int1 -eq int2 | int1 == int2 | เป็นจริงเมื่อ int1 เท่ากับ int2 |
| int1 -ge int2 | int1 >= int2 | เป็นจริงเมื่อ int1 มากกว่าหรือเท่ากับ int2 |
| int1 -gt int2 | int1 > int2 | เป็นจริงเมื่อ int1 มากกว่า int2 |
| int1 -le int2 | int1 <= int2 | เป็นจริงเมื่อ int1 น้อยกว่าหรือเท่ากับ int2 |
| int1 -lt int2 | int1 < int2 | เป็นจริงเมื่อ int1 น้อยกว่า int2 |
| int1 -ne int2 | int1 != int2 | เป็นจริงเมื่อ int1 ไม่เท่ากับint2 |
| คำสั่งเกี่ยวกับ String | ||
| str1 = str2 | str1 == str2 | เป็นจริงเมื่อ str1 เหมือนกับ str2 |
| str1 != str2 | str1 != str2 | เป็นจริงเมื่อ str1 ไม่เหมือนกับ str2 |
| str | เป็นจริงเมื่อ str ไม่เป็น null | |
| -n str | เป็นจริงเมื่อ str มีความยาวมากกว่า 0 | |
| -z str | เป็นจริงเมื่อ str มีความยาวเป็น 0 | |
| คำสั่งเกี่ยวกับ file | ||
| -d filename | -d filename | เป็นจริงเมื่อ filename เป็น directory |
| -f filename | -f filename | เป็นจริงเมื่อ filename เป็น file |
| -r filename | -r filename | เป็นจริงเมื่อ filename อ่านได้โดยโปรแกรม |
| -s filename | เป็นจริงเมื่อ filename มีขนาดไม่เป็น 0 | |
| -w filename | -w filename | เป็นจริงเมื่อ filename เขียนได้โดยโปรแกรม |
| -x filename | -x filename | เป็นจริงเมื่อ filename run ได้โดยโปรแกรม |
| -e filename | เป็นจริงเมื่อ filename มีชื่ออยู่ | |
| -o filename | เป็นจริงเมื่อ filename เป็นของผู้ใช้ปัจจุบัน | |
| -z filename | เป็นจริงเมื่อ filename มีขนาดเป็น 0 | |
| คำสั่งเกี่ยวกับ Logical อื่นๆ | ||
| ! expr | ! expr | เป็นจริงเมื่อ exp เป็นเท็จ |
| exp1 -a exp2 | exp1 && exp2 | เป็นจริงเมื่อ exp1 และ exp2 เป็นจริง |
| exp1 -o exp2 | exp1 || exp2 | เป็นจริงเมื่อ exp1 หรือ exp2 เป็นจริง |
เงื่อนไข if
โครงสร้าง
| bash / ksh | tcsh |
| if [expression ] |
then
commands
elif [ exprression ]
then
commands
else
commands
fiif (expression) then
commands
else if (expression) then
commands
else
commands
endif
ทั้งนี้จะมี elif หรือ ไม่มี else ก็ได้
ตัวอย่างการใช้งาน เช่น
#! /bin/ksh
if [ -f .signature ]
then
echo “There is .signature file in
this current directory”
else
echo “File .signature could not be
found.
fi
เงื่อนไข case หรือ switch
โครงสร้าง
| bash / ksh | tcsh |
| case string in |
str1)
commands;;
str2)
commands;;
str3)
commands;;
*)
commands;;
esacswitch(string)
case str1:
commands
breaksw
case str2:
commands
breaksw
case str3:
commands
breaksw
default:
commands
breaksw
endsw
ในกรณีของ bash และ ksh นั้น จะใช้ ;; แทน break
ตัวอย่างการใช้งาน เช่น
#! /bin/ksh
# Sample switch case
if [ $# -lt 2 ]
then
echo “Using : $0 [a | b | c] filename”
else
case $1 in
“a” | “A”)
cat $2;;
“b” | “B”)
&nsbp; more $2;;
“c” | “C”)
less $2;;
*)
echo “I Don’t understand $1″
esac fi
เงื่อนไข for
โครงสร้าง
| bash / ksh | tcsh |
| for var in list |
do
commands
doneforeach var (list)
commands
end
ตัวอย่างการใช้งาน เช่น
#! /bin/ksh
# Sample for
for x in “a ” “b” “x*”
do
if [ -f "$x" ]
then
echo “— found $x —”
else
echo “— Not found $x —”
fi
เงื่อนไข while
โครงสร้าง
| bash / ksh | tcsh |
| while [ expression ] |
do
commands
donewhile (expression)
commands
end
ตัวอย่างการใช้ while เช่น
#! /bin/ksh
count=1
while [ -n "$*" ]
do
echo “This is parameter no $count $1″
shift
count=`expr $count+1`
done
เงื่อนไข until
โครงสร้าง
| bash / ksh | tcsh |
| until [ expression ] |
do
commands
doneไม่สนับสนุน
เงื่อนไข repeat
| bash / ksh | tcsh |
| ไม่สนับสนุน | repeat count command |
ตัวอย่างการใช้ repeat เช่น
#! /bin/tcsh
repeat $num echo -n “+”
echo “”
คำสั่งอื่นๆ ที่ช่วยให้เขียน Interactive
Shell Script ได้ง่ายขึ้น
คำสั่ง read
ใช้สำหรับอ่านค่าตัวแปรจาก Standard Input เช่น
#! /bin/ksh
echo -n “Enter FirstName Lastname”
read x y
echo “”
echo “Your firstname is $y, $x.”
คำสั่ง echo
ใช้เพื่อการแสดงข้อความ
คำสั่ง shift
ใช้สำหรับการ Shift ค่าตัวแปรใน $* ไป 1 ตำแหน่ง
การสร้างคำสั่งใหม่ (Function)
โครงสร้าง
| bash / ksh | tcsh |
| [function] fname { |
(shell commands)
}ไม่สนับสนุน
ซึ่งเราสามารถเรียกใช้ Function ได้โดย
fname [ parm1 parm2 parm3 ... ]
ตัวอย่างเช่น
#! /bin/bash
print () {
echo $1 $2;
}
a=10;
b=20;
print $a $b
การประมวลผลทางคณิตศาสตร์ และ expression
เราสามารถประมวลผลบวกลบคูณหาร หรือ expression ต่างๆ ได้โดยใช้โปรแกรม expr ช่วย เช่น
a=`expr $a + 1` หรือ set a=`expr $a + 1`
ในกรณีของ bash เราสามารถใช้ a=$(($a + 1 )) แทนได้เลย
ข้อควรระวังคือ จะต้องมีการเว้นวรรคระหว่าง ตัวแปร ค่าคงที่ และ
เครื่องหมาย (มิเช่นนั้น จะได้ผลลัพธ์เป็น string ต่อกัน)
เครื่องหมายและการปฏิบัติการที่ใช้ได้ใน expr คือ +, -, *, / , % (modulo
หรือ หารเอาเศษ) นอกจากนี้ยังมีการเปรียบเทียบต่างๆ เช่น =, \<, \>,
\<=, \>=, และ != (กรณีใช้กับ bash $(( expression ))
ให้นำเครื่องหมาย \ ออก การเปรียบเทียบเหล่านี้จะให้ผลลัพธ์เป็น 0
หากเป็นเท็จ และ 1 หากเป็นจริง
เกร็ดเล็กน้อยเกี่ยวกับการใช้ expr
expr1 \| expr2
จะแสดงผลลัพธ์จาก expr2 หาก expr1 เป็น 0 หรือ NULL เช่น
expr 1 – 1 \| “zero”
จะได้ผลลัพธ์เป็น “zero” เนื่องจาก 1 – 1 = 0 เป็นต้น
expr1 \& expr2
จะแสดงผลลัพธ์จาก expr1 หาก ไม่มีอันใดเป็น 0 หรือ NULL เช่น
expr valid \& 3 – 2 \& 4
จะได้ผลลัพธ์เป็น “valid” เนื่องจากไม่มี expression ใด เป็น 0 เป็นต้น
expr1 : expr2
จะเปรียบเทียบ expr1 กับ expr2 ตามมาตรฐาน regular expression เช่น
expr $HOME : “.*home.*”
จะตรวจสอบว่ามีคำว่า home อยู่ใน $HOME หรือไม่ เป็นต้น
เอกสารอ้างอิง
- T. Parker, Chapter 13 Shell Programming ,”Slackware Linux”,
SAMS Publishing, 3rdEdition, 1997. - ksh , sh , tcsh , bash manpage.
Computer Architecture