Note13.txt -- คำบรรยายประจำสัปดาห์ ตอนที่ ๑ Configuration file ของ vi --------------------------------- แฟ้มควบคุม/ปรับแต่งการทำงานของโปรแกรม (configuration file หรือ run control) ของระบบปฏิบัติการ Unix จัดเก็บไว้ที่ home directory ของผู้ใช้แต่ละคน แฟ้มควบคุมการทำงานของ bash (Bourne again shell) ที่ใช้งานในภาคเรียนนี้คือ .bash_profile ค่าของ terminal ที่กำหนดที่นิยมใช้มีสองแบบคือ TERM=vt100 vt100 เป็นจอภาพเอกรงค์ เมื่อเรียกใช้งานโปรแกรม vi รุ่นปัจจุบัน จะมีการเน้นไวยากรณ์ของภาษาให้เด่น (highlight) เช่นไวยากรณ์ของภาษา c, c++ และ java โดยอัตโนมัติ เนื่องจากเป็จอภาพเอกรงค์ จึงแสดงการ "เน้น" ด้วย ตัวเข้ม และ ตัวขีดเส้นใต้ เป็นต้น ในบางกรณีทำให้อ่านยาก โดยเฉพาะเมื่อการใช้เครื่องหมาย underscore, "_" หากต้องการยกเลิก ทำได้โดยเข้าสู่ last line mode ของ vi โดยการกดแฟ้น Esc ตามด้วย :, vi จะแสดงเครื่องหมาย colon ที่บรรทัดล่างสุด เพื่อรับคำสั่ง ให้พิมพ์คำสั่งดังนี้ :syntax off หากต้องการยกเลิกการเน้นให้เด่นเป็นการถาวร ต้องกำหนดในแฟ้ม run control ของ vi ชื่อแฟ่ม .exrc ที่ home directory และเพิ่มคำสั่ง syntax off ในแฟ้ม แฟ้ม .exrc เป็นแฟ้มควบคุมการทำงานโปรแกรม ex ซึ่งเป็นต้นกำเนินของโปรแกรม vi ในกรณีที่ต้องการกำหนดการเน้นไวยากรณ์ให้เด่นด้วยสี ต้องกำหนดให้ terminal เป็นจอสีคือ TERM=xterm xterm เป็นจอภาพที่แสดงสีได้ 8 สี ซึ่งเพียงพอสำหรับการเน้นสีตัวอักษร หากไม่ชอบการเน้นแบบนี้ ยกเลิกด้วยคำสั่ง syntax off ได้เช่นเดียวกับจอภาพเอกรงค์ ::หมายเหตุ:: vi ที่ใช้งานในระบบในปัจจุบันคือโปรแกรม vim (vi improved) version 7.4 (ตรวจสอบด้วย vi --version) ชื่อ vi เป็น symbolic link ต่อเนื่องไปดังนี้ vi = /usr/bin/vi -----> /etc/alternatives/vi -----> /usr/bin/vim.basic การเน้นไวยากรณ์ (syntax hightlight) ในภาษาใด ต้องมีแฟ้มสนับสนุน "ชื่อภาษา.vim" เช่น gcc.vim, sh.vim และ java.vim เป็นต้น ในไดเรกทอรี /usr/share/vim/vim74/syntax ตอนที่ ๒ standard input และ arguments ------------------------------------ standard input และ command line arguments เป็นช่องทางการรับข้อมูลเข้าของโปรแกรม 1. รับข้อมูลเข้าทาง standard input เป็นการรับค่าเก็บในโปรแกรมด้วยคำสั่ง read เหมาะสำหรับโปรแกรมที่มีการโต้ตอบกับผู้ใช้ (interactive program) -- โปรแกรมแสดงข้อความรับข้อมูล ผู้ใช้ป้อนข้อมูล โปรแกรมที่รับข้อมูลเข้าทาง standard input สามารถเปลี่ยนทิศทางการรับข้อมูลเข้าจากแฟ้มได้ โดยใช้ redirection operator $ ชื่อโปรแกรม < data.txt อ่านข้อมูลจากแฟ้ม data.txt แทนแป้นพิมพ์ 2. รับข้อมูลผ่าน command line arguments เช่น $ ชื่อโปรแกรม อาร์กิวเมนต์_1 อาร์กิวเมนต์_2 อาร์กิวเมนต์_3 ... ... ... เมื่อโปรแกรมทำงาน จะรับ "รายการ" อาร์กิวเมนต์ของผู้ใช้ผ่าน positional parameters, $1 $2 $3 ... ตามลำดับ แนวทางปฏิบัติที่เกี่ยวกับ standard input และ command line arguments สรุปได้ดังนี้ ก. เมื่อต้องการนำ standard output ของโปรแกรมหนึ่ง ไปใช้เป็น standard input ของอีกโปรแกรมหนึ่ง ทำได้โดยการนำโปรแกรม หรือคำสั่งที่ต้องการ มาเชื่อมต่อเป็น pipeline $ โปรแกรม_1 | โปรแกรม_2 | โปรแกรม_3 | ... บรรทัดคำสั่งนี้เป็นการ - นำ standard output ของ โปรแกรม_1 ไปเป็น standard input ของ ของ โปรแกรม_2, - นำ standard output ของ โปรแกรม_2 ไปเป็น standard input ของ ของ โปรแกรม_3, เป็นเช่นนี้เรื่อยจนกว่าจะหมดคำสั่งใน pipeline ข. เมื่อต้องการนำ standard output ของโปรแกรมหนึ่ง ไปใช้เป็น "อาร์กิวเมนต์" ของอีกโปรแกรมหนึ่ง ทำได้โดยการแทนคำสั่งด้วยผลลัพธ์ หรือการทำ command substitution, $(...) หรือ `...` $ โปรแกรม_1 $(โปรแกรม_2 รายการอาร์กิวเมนต์) บรรทัดคำสั่งนี้กำหนดให้โปรแกรม_2 ทำงานตามรายการอาร์กิงเมนต์ที่กำหนด (ถ้ามี) และนำ standard output ของโปรแกรมนั้น แทนที่โปรแกรม_2 เพื่อใช้เป็นอาร์กิวเมนต์ของโปรแกรม_1 ค. ในกรณีที่ต้องการนำ standard input ที่ได้รับจาก pipe เป็นอาร์กิวเมนต์ของโปรแกรมที่อยู่ถัดไปใน pipeline ต้องใช้โปรแกรมช่วยนำข้อมูลที่ได้รับจาก standard input มาจัดเป็นอาร์กิวเมนต์ของโปรแกรมที่กำหนด คือโปรแกรม xargs และเมื่อจัดบรรทัดคำสั่งเรียบร้อยแล้วจะกำหนดให้บรรทัดคำสั่งนั้นทำงาน $ โปรแกรม_1 | xargs โปรแกรม_2 คำสั่ง xargs ทำหน้าที่สร้างบรรทัดคำสั่ง ประกอบด้วยโปรแกรม_2 และนำข้อมูลที่ได้รับจาก pipe สร้างเป็นอาร์กิวเมนต์ และทำงานตามบรรทัดคำสั่งนั้น (build and execute command lines from standard input) ตอนที่ ๓ โปรแกรมพิมพ์สูตรคูณมาตรา m - n ----------------------------------- แสดงในรูปแบบของคำถาม-คำตอบ Q: จะพิมพ์สูตรคูณมาตรา m เพียงมาตรเดียว เช่น มาตรา 9 ได้อย่างไร? A: ใช้โครงสร้าง for ที่มี "รายการ" แบบกำหนดพิสัย m=9 for i in {1..12}; do ... ... (1) echo "$m x $i = $(($m * $i))" ... ... (2) done ... ... (3) - คำสั่งบรรทัด (1) - (3) มีฐานะ "เสมือนเป็นคำสั่งเดียว" คือ เป็นคำสั่งพิมพ์สูตรคูณมาตรา m - การพิมพ์สูตรคูณมาตรา m - n เป็นการทำ loop ครอบคำสั่งนี้ โดยเริ่มทำเมื่อ m มีค่าเป็นมาตราเริ่มต้น เมื่อพิมพ์เสร็จ พิมพ์มาตรา m + 1 เรื่อยไปจนกว่าจะถึงมาตรา n Q: สามารถกำหนดพิสัยโดยใช้ตัวแปรได้ เช่น {$m..$n} ได้หรือไม่? A: สามารถนำ {$m..$n} ใช้ในโครงสร้าง for ได้โดยไม่ผิดไวยากรณ์ แต่จะมีความหมายเป็นรายการที่มีสมาชิกเพียงตัวเดียว คือสายอักขระ "$m..$n" จึงมีการทำงานซ้ำเพียงครั้งเดียว โดยมีค่าของ i เป็น "{$m..$n}" Q: เมื่อใช้การทำซ้ำแบบ for ไม่ได้ จะทำอย่างไร? A: นอกจาก for ยังมีดครงสร้างทำซ้ำแบบ while และ repeat..until while - ทำซ้ำในขณะที่เงื่อนไขเป็นจริง เช่นเดียวกับ while ในภาษา C until - ทำซ้ำจนกว่าเงื่อนไขจะเป็นจริง คล้ายโครงสร้าง do..while ในภาษา C แต่ไม่เหมือนเพราะ do..while ทำซ้ำ ในขณะที่เงื่อนไขเป็นจริง Q: โครงสร้าง while มีรูปแบบทางไวยากรณ์อย่างไร? A: รูปแบบทั่วไปเป็นดังนี้ while [ ... ] ; do # เงื่อนไขของ while เป็นคำสั่งใดๆ, ส่วนใหญ่เป็นคำสั่ง test ... ... ... # "งาน" ที่ต้องการให้ทำซ้ำ เมื่อ "เงื่อนไข" เป็นจริง done ... ... ... # เมื่อเงื่อนไขเป็นเท็จ ออกจากโครงสร้างมาทำงานต่อที่จุดนี้ Q: ขอดูตัวอย่างอย่างง่ายของ while A: ดัดแปลงคำสั่งพิมพ์สูตรคูณมาตรา m จาก for เป็น while โครงสร้าง for โครงสร้าง while ----------- -------------- m=9 m=9 i=1 for i in {1..12}; do while [ $i -le 12 ]; do echo "$m x $i = $(($m * $i))" echo "$m x $i = $(($m * $i))" done i=$(($i + 1)) done จากตัวอย่าง สิ่งที่ต้องเพิ่มเข้ามาในโครงสร้าง while คือ (๑). กำหนดค่าเริ่มต้นของตัวแปร i, (๒). กำหนดเงื่อนไขทดสอบ ว่าตัวแปร i มีค่าถึง 12 หรือยัง และ (๓). การเพืมค่าตัวแปร i เมือมีการทำงานในแต่ละรอบ -- ในขณะที่งานเหล่านี้เกิดขึ้น โดยอัตโนมัติในโครงสร้าง for จึงมีผู้เรียกโครงสร้าง for ว่าเป็นโครงสร้างทำซ้ำอัตโนมัติ (automatic loop) -- เมื่อต้องใช้โครงสร้าง while อย่าลืมเรื่องสามประการนี้ Q: โครงสร้าง while ของการพิมพ์สูตรคูณมาตรา m - n เมื่อ m <= n A: โครงสร้างอย่างง่ายเป็นดังนี้ กำหนดค่าของ m และ n # เช่น m=5; n=7 เมื่อ m <= n while [ $m -le $n ]; do พิมพ์สูตรคูณมาตรา m # มีอยู่แล้วจะใช้แบบ for หรือ while ก็ได้ เพิ่มค่า m ไปยังมาตราต่อไป # m=$((m + 1)) done นำมารวมกัน m=5; n=7 while [ $m -le $n ]; do for i in {1..12}; do echo "$m x $i = $(($m * $i))" done done Q: ค่า m และ n ในโปรแกรมนี้มีค่าตายตัว ทุกครั้งที่ทำงานจะได้สูตรคูณมาตรา 5 - 7 เสมอ ค่าของ m และ n ในกรณีเช่นนี้ มีชื่อเรียกเฉพาะว่า hard code เป็นวิธีการที่ไม่เหมาะสมในการเขียนโปรแกรม ทำอย่างไรผู้ใช้จะกำหนดค่าของ m และ n ก่อนการทำงานได้? A: ทำได้สองแบบคือ - รับข้อมูลทาง standard input เป็นโปรแกรมโต้ตอบกับผู้ใช้ โดยใช้คำสั่ง read เช่น echo "Enter starting and ending multiplication table."; echo -n "start: "; read m echo -n "end: "; read n จะได้มาตราเริ่มต้นในตัวแปร m และมาตราสุดท้ายในตัวแปร n - รับข้อมูลผ่านอาร์กิวเมนค์ของบรรทัดคำสั่ง (command line arguments) เช่น ต้องการพิมพ์สูตรคูณมาตรา 5 - 7 $ multab 5 7 ระบบเก็บมาตราเริ่มต้นในตัวแปร $1 และมาตราสุดท้ายในตัวแปร $2 ซึ่งสามารถนำไปใช้งานในโปรแกรมได้โดยตรง หรือ จะนำมากำหนดให้ตัวแปร m และ n ก่อนก็ได้ เช่น m=$1; n=$2 การกำหนดเช่นนี้จะมีประโยชน์ในกรณีที่ตอ้งการสลับค่าของพารามิเตอร์ตัวแรกและตัวที่สอง Q: ถ้าสามารถรับข้อมูลเข้าได้สองแบบ ควรเลือกใช้วิธีการแบบใด? A: ขึ้นอยู่กับความต้องการของผู้ใช้ หากต้องการโปรแกรมชนิดโต้ตอบกับผู้ใช้ (interactive program) หรือต้องการนำโปรแกรม ไปใช้ใน pipeline ควรเลือกใช้การรับข้อมูลผ่าน standard input โดยใช้คำสั่ง read แต่หากต้องการนำโปรแกรมนั้นไปใช้เป็น ส่วนหนึ่งของ script อื่น ควรเลือกแบบอาร์กิวเมนต์ ซึ่งเป็นรูปแบบที่โปรแกรมอรรถประโยชน์ส่วนใหญ่ใน Unix ใช้งาน Q: หากเลือกแบบรับข้อมูลผ่าน command line arguments และผู้ใช้ป้อนข้อมูลสลับกัน เช่นต้องการพิมพ์สูตรคูณมาตรา 5 - 7 แต่พิมพ์คำสั่งเป็น $ multab 7 5 A: ข้อมูลของผู้ใช้แบบนี้ ยังไม่จัดเป็น "ความผิดพลาด" เพราะพิสัยอยู่ในย่านที่ถูกต้อง แนวปฏิบัติมีสองแบบคือ (๑). พิมพ์สูครคูณ มาตรา 7, 6, และ 5 ตามลำดับ โดยต้องจัดตัวแปรและเงื่อนไขของโครงสร้าง while ใหม่ โปรแกรมจะมี 2 กรณี คือเมื่อ m <=n และ m > n หรือ (๒). สลับค่าเริ่มต้นและค่าสุดท้าย และใช้โปรแกรมเดิมไม่ต้องแก้ไข ซึ่งเป็นวิธีที่ดีกว่า m=$1; n=$2 if [ $1 -gt $2 ]; them if [ $1 -gt $2 ]; then m=$2; n=$1 m=$2; n=$1 else fi m=$1; n=$2 fi นำมารวมกัน m=$1; n=$2 if [ $1 -gt $2 ]; then m=$2; n=$1 fi while [ $m -le $n ]; do for i in {1..12}; do echo "$m x $i = $(($m * $i))" done done Q: การจัดการกับ error ควรมีอะไรบ้าง? A: ก. การตรวจสอบจำนวนอาร์กิวเมนต์, ($#) เป็นรูปแบบมาตรฐานอยู่แล้ว แต่ต้องดัดแปลงข่าวสารให้เหมาะกับงาน ข. การตรวจสอบว่าอาร์กิวเมนต์เป็นตัวเลขหรือไม่ โดยใช้นิพจน์ปรกติ เคยใช้งานมาแล้ว เพียงแต่ต้องตรวจสอบ พารามิเตอร์ทั้งสองตัวคือ $1 และ $2 ค. และในทำนองเดียวกกัน การตรจสอบว่าพารามิเตอร์ที่ได้รับอยู่ในช่วง 2 - 25 หรือไม่ต้องทำทั้งสองตัวคือ $1 และ $2 Q: การตรวจสอบว่า n อยู่ในช่วง 2 - 25 หรือไม่ ควรใช้รูปแบบอย่างไร? A: n มีค่าอยู่ในช่วง 2 - 25 เขียนเป็นนิพจน์คณิตศาสตร์ได้เป็น 2 <= n <=25 - ต้องแยกเป็นนพจน์ตรรกะ 2 ชุด คือ 2 <= n (หรือ n >= 2) และ n <= 25 (หรือ 25 >= n) - เลือกใช้ n >= 2 และ n <= 25 ซึ่งความจริงจะเลือกแบบใดก็ได้ เพราะมีความหมายเหมือนกัน - เมื่อต้องการใช้นิพจน์ตรรกะสองชุดร่วมกัน เพื่อให้ได้ "ค่าความจริง" ค่าเดียว ต้องใช้ logical connective, and หรือ or 1. n <= 2 and n <=-25 ข้อมูลอยู่ในช่วง 2 - 25 --> ข้อมูลถูกต้อง 2. n < 2 or n > 25 ข้อมูลอยู่นอกพิสัยที่กำหนด --> แสดง error และเลิกทำงาน - การเขียนโปรแกรมระบบ ใช้วิธีการตรวจจับ "ข้อมูลที่ผิดพลาด" แสดง error mesage และเลิกทำงาน - connective ใน bash ใช้ -a แทน and และ -o แทน or if [ $n -lt 2 -o $n -gt 25 ]; then แสดงข่าวสารความผิดพลาด เลิกทำงาน # exit <รหัสความผิดพลาด> fi Q: การตรวจสอบทั้ง m และ n พร้อมกันว่าอยู่ในช่วง 2 - 25 หรือไม่ ควรทำอย่างไร? A: เขียนเงื่อนไขของ m และ n แยกกัน แลัวเชื่อมด้วย logical connective ของเชลล์, && แทน and และ || แทน or if [ $m -lt 2 -o $m -gt 25 ] || [ $n -lt 2 -o $n -gt 25 ]; then ... ... ... เมื่อรวมทั้งหมดนี้เข้าด้วยกัน จะได้โปรแกรมที่สมบูรณ์ Q: จะเลือกตัวอย่าง m และ n อย่างไร จึงจะแน่ใจได้ว่าโปรแกรมนี้ทำงานถูกต้องตามที่กำหนดไว้ทุกกรณีหรือไม่? A: เป็นแบบฝึกหัดสำหรับผู้เรียน ตอนที่ ๔ อนุกรม Fibonacci และ sliding window ------------------------------------------- ก. อนุกรม Fibonacci มีสมาชิกดังนี้ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... สมาชิกลำดับที่ n คำนวณได้จาก F[n] = F[n-1] + F[n-2] เมื่อกำหนดให้ F[0] = 0 และ F[1] = 1 ข. sliding window เป็นรายการย่อย (sublist) ที่ทำงานอยู่เหนือรายการใหญ่ เช่น หากมีรายการ [ a b c d e f g h ] sliding window ที่มีขนาดเป็น 3 จะทำงานผ่านรายการทั้งหมดดังนี้ [ a b c ] [ b c d ] [ c d e ] [ d e f ] [ e f g ] [ f g h ] การสร้างสมาชิกของอนุกรม Fibonacci โดยใช้เทคนิค sliding window อนุกรม Fibonacci [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... ] สมาชิกลำดับที่ n, คำนวณจาก F[n] = F[n-1] + F[n+1] หรือเป็นสมการ second order recurrence ต้องพิจารณาสมาชิกครั้งละ 3 ตัว ดังนั้นขนาดของ window = 3 สมาชิกสองตัวแรกของอนุกรม มาจากการกำหนดคือ F[0] = 0 และ F[1] = 1 fa fb fc [ 0 1 ? ] fc = fb + fa = 1 ก่อนจะทำงานครั้งต่อไป ต้องเลื่อน window ไปทางขวา 1 ตำแหน่ง ทำให้ fb กลายเป็น fa, และ fc กลายเป็น fb หรือ fa = fb; และ fb = fc fa fb fc 0 [ 1 1 ? ] fc = fb + fa = 2 เลื่อน window ไปทางขวา 1 ตำแหน่ง ทำให้ fa = fb; และ fb = fc fa fb fc 0 1 [ 1 2 ? ] fc = fb + fa = 3 ... ... ... เมื่อเข้าใจการทำงานแล้ว เขียนเป็น shell script ได้ดังนี้ # ก่อนเริ่มทำงานมีจำนวนสมาชิก 2 ตัวที่รู้ค่าแล้ว คือ fa = 0; fb = 1 } fa = 0; fb = 1 n=2 # จำนวนสมาชิก echo -n "$fa, $fb" until [ n -eq 15 ]; do # จนกว่าจะมีสมาชิกครบ 15 ตัว fc=$(($fb + $fa)) echo -n ", $fn" # พิมพ์สมาชิกใหม่ที่คำนวณได้ fa=$fb # เลื่อน window ไปทางขวา 1 ตำแหน่ง fb= $fc n=$((n + 1)) # เพิ่มจำนวนสมาชิก done echo โครงสร้างทำซ้ำที่ใช้ นอกจาก until แล้ว สามารถใช้ while และ for ได้ ลองเขียนดู และ หากสนใจเรื่องของอนุกรม Fibonacci, สัดส่วนทองคำ (golden ratio) และอนุกรม Fibonacci ที่พบในธรรมชาติ ลองดูจาก "Fibonacci Numbers and Nature" ที่ http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibnat.html ตอนที่ ๕ เรื่องบางประเด็น จากโปรแกรม lnks.sh -------------------------------------- ก. หากชื่อแรกเป็นไดเรกทอรี จะไม่สามารถทำงานได้ ระบบปฏิบัติการ Unix ไม่อนุญาตให้ผู้ใช้สร้าง hard link ไปยังไดเรกทอรี เพราะหากผู้ใช้ไม่ระมัดระวังหรือมีความเข้าใจไม่เพียงพอ อาจทำให้เกิดการอ้างอิงเป็นวงขึ้นได้ในระบบแฟ้ม เช่นการสร้าง hard link ของไดเรกทอรีปัจจุบัน ไปยังไดเรกทอรีแม่ ซึ่งจะทำให้เกิดการอ้างอิงวนเป็นวงไม่รู้จบ ด้วยเหตุนี้หากพารามิเตอร์ตัวแรกเป็นชื่อไดเรกทอรี ควรแจ้งให้ผู้ใช้ทราบและแสดงรูปแบบการใช้คำสั่งที่ถูกต้อง ข. แสดงการใช้งาน default argument ค่าโดยปริยาย ------------------------------------------------------------------------------------------------------- ก่อนจะอธิบาย ขอนิยามศัพท์ให้เข้าใจตรงกันก่อน ตัวแปรสำหรับ "รับข้อมูล" ของฟังก์ชัน เรียกว่า formal parameters เช่น double square ( double x ); # prototype ของฟังก์ชัน square มี x เป็น formal parameter ผู้เรียกส่ง "ค่า" ที่ต้องการดำเนินการมาให้ฟังก์ชัน (ซึ่งต้องสมนัยกับตัวแปรที่รับ) ค่านี้เรียกว่า actual parameters เช่น y = square(12.36); # 12.36 คือค่าจริง ที่ต้องการให้ฟังก์ชันดำเนินการ (actual parameter) เมื่อมีการเรียกใช้งาน ฟังก์ชัน square จะรับค่า 12.36 ในตัวแปร x คำว่า formal parameters และ actual parameters มีสองคำ อาจเรียกไม่สะดวก ในกรณีที่ต้องการย่อ นิยมใช้คำว่า "argument" แทน actual parameter และคำว่า "parameter" แทน formal parameter - ผู้เรียกส่งอาร์กิวเมนต์ให้ฟังก์ชัน ฟังก์ชันรับเก็บในพารามิเตอร์ - อาร์กิวเมนต์และพารามิเตอร์จึงเป็น "สิ่ง" เดียวกัน ขึ้นอยู่กับมุมมอง ว่าเป็นผู้เรียก หรือผู้ถูกเรียก ------------------------------------------------------------------------------------------------------- default argument เป็นค่าที่กำหนดให้กับพารามิเตอร์ของฟังก์ชัน หรือโปรแกรม ในกรณีที่ไม่มีการกำหนดอาร์กิวเมนต์นั้นในขณะเรียกใช้ โดยจะดำเนินการโดยอัตโนมัติเมื่อมีเรียกใช้งาน เป็นลักษณะที่สำคัญอย่างหนึ่งของภาษาในยุคปัจจุบัน เช่น C++, Java ภาษา script เช่น PHP เป็นต้น ในกรณีที่ต้องการ ผู้เขียน shell script สามารถเขียนโปรแกรมเลียนแบบได้ เช่นโปรแกรม lnks.sh ซึ่งกำหนดรูปแบบการใช้งานไว้เป็น $ lnks.sh <ชื่อแฟ้ม> [<ชื่อไดเรกทอรี>] ในกรณีที่ผู้ใช้กำหนดชื่อไดเรกทอรี โปรแกรมจะดำเนินการในไดเรกทอรีที่ผู้ใช้กำหนด, หากผู้ใช้ไม่กำหนดชื่อไดเรกทอรี โปรแกรมจะกำหนดให้เป็นไดเรกทอรีปัจจุบันโดยปริยาย การเขียนโปรแกรมเช่นนี้ทำให้ผู้ใช้เห็นว่าโปรแกรม "ฉลาด" คิดเองได้ แต่ความเป็นจริงเป็นความ "ฉลาด" ของผู้เขียนโปรแกรม