สร้าง CLI แรกของคุณด้วย Shell Script
บทความนี้จะพาไปสร้าง CLI เป็นของตัวเอง สามารถนำไปเป็นปรับใช้กับงานอื่นๆ หรือสามารถใช้งาน command, option และ help รวมถึงเทคนิคการ export PATH, Dotfile และชนิดของ shell
CLI (Command Line Interface)
CLI (Command Line Interface) คือแอปพลิเคชันซอฟต์แวร์ที่ช่วยให้ผู้ใช้สามารถติดต่อกับโปรแกรมโดยใช้คำสั่งที่พิมพ์ผ่านหน้าจอคำสั่ง (Text-based) ซึ่งต่างจากหน้าจอผู้ใช้แบบกราฟิก (GUI) โดย CLI ทำงานใน Terminal หรือ Console ซึ่งเหมาะกับงาน software develoment, network และงาน system เนื่องจากมีประสิทธิภาพสูงและสามารถทำ automate ต่าง ๆ ผ่านสคริปต์ได้. CLI ที่นิยมเช่น Git, ตัวจัดการแพ็คเกจเช่น apt หรือ npm หรือแม้แต่ command พื้นฐานอย่าง ls, rm and mkdir และอื่นๆ
ข้อดีของ Command Line Interface (CLI)
1. Automate: CLI ช่วยในการสร้างสคริปต์และการทำงานอัตโนมัติ, เพิ่มประสิทธิภาพในการดำเนินการงานหรือการบริหารจัดการระบบ.
2. Light weight: CLI มีการใช้ทรัพยากรน้อยกว่า GUI, ทำให้เหมาะสำหรับการใช้งานในสภาพแวดล้อมที่ทรัพยากรมีจำกัด และต้องการความรวดเร็ว
3. Flexibility: ผู้ใช้สามารถทำงานด้วยคำสั่งที่กำหนดเอง, เพิ่มความยืดหยุ่นในการปรับแต่งการทำงาน.
CLI มีข้อดีเหล่านี้ทำให้เป็นเลือกที่น่าสนใจสำหรับผู้ใช้ที่ต้องการความรวดเร็ว, ความยืดหยุ่น, และความสามารถในการทำงานอัตโนมัติ.
เชื่อว่าผู้เริ่มเป็น developer ทุกคนต้องเคยใช้ Command-Line Interface (CLI) มามากพอสมควร ยกตัวอย่างเช่น
git commit -m "inint cli project"
git ก็เป็น CLI อันหนึ่งซึ่ง 1 บรรทัดนี้ประกอบด้วย
git commit
เป็น command ใช้เพื่อทำการ commit ความเปลี่ยนแปลงใน code ของโปรเจค-m
เป็น option ใช้เพื่อระบุข้อความ commit ที่อธิบายถึง code ที่ถูก เพิ่ม/แก้ไขinit cli project
เป็น value ที่อธิบายถึงการ commit นี้, ซึ่งควรเป็นอธิบายที่สั้นและกระชับเกี่ยวกับ code
Design your own CLI
ก่อนอื่นเรามา design interface ของ CLI กันก่อน
ให้โจทย์เราคือสร้าง CLI ชื่อ thaitools
และ command idcard
สำหรับ generate เลขบัตรประชน
- CLI name:
thaitools
- Command:
idcard
สำหรับ gen บัตรประชาชน - Option:
-n
,--num-cards
เป็น option สำหรับระบุ จำนวน id ที่เราอยากให้ gen - Option:
-f
,--file
เป็น option สำหรับระบุ path file ให้เขียนลง file - Option:
-h
,--help
แสดงคู่มือการใช้งาน CLI
ตัวอย่าง CLI ที่เราอยากให้เป็น
# Terminal
thaitools idcard -n 5 -f ~/Desktop/idCards.txt
# output
Generated Card Number 1: 4525559316227
Generated Card Number 2: 7490467785663
Generated Card Number 3: 4142313773738
Generated Card Number 4: 5250857640495
Generated Card Number 5: 2620161605665
Setup script
1. สร้าง file สำหรับ CLI ชื่อ thaitools ใช้คำสั่ง touch <file_name>
# Terminal
touch thaitools
2. change mode ให้เป็น executable file หรือ Unix Executable File
# Terminal
chmod +x thaitools
เราสามารถ ข้ามขั้นตอนนี้ถ้าเราต้องการสร้างแค่ shell script file โดยการ run ผ่านคำสั่ง `sh thaitools.sh`
3. write code
#!/bin/sh
echo "hello world"
สำหรับระบบ unix หรือ linux ที่เราคุ้นเคยกัน เรามักจะคุ้นตากับ บรรทัดแรกของ script ต่างๆ ขึ้นต้นด้วย #!/bin/bash หรือ #!/bin/sh
ทำไมถึงต้องมี? ก็เพื่อต้องบอกให้รู้ว่า script นี้ควรจะถูก execute ด้วย bash หรือ sh บนระบบ unix หรือ linux รูปแบบของ #! บนบรรทัดแรกของ script ไม่ได้จำกัดอยู่แค่บน bash หรือ sh เท่านั้นแต่ยังรวมไปถึง interpreter ตัวอื่นๆได้ด้วย มันมีชื่อเรียกว่า “Shebang” เราสามารถ execute python , ruby ,node ได้ด้วยการแปะ Shebang ลงไปใน script เช่น
#!/bin/bash
#!/usr/local/bin/ruby หรือ #!/usr/bin/env ruby
#!/usr/local/bin/python หรือ #!/usr/bin/env python
#!/usr/local/bin/node หรือ #!/usr/bin/env node
4. run ทดสอบ script
# Terminal
./thaitools
# output
hello world
ถ้าขึ้น hello world เป็นอันว่า script เราทำงานได้
เริ่มเขียน shell script ให้ generate เลขบัตรประชาชน
ขั้นตอนการสร้างเลขบัตรประชาชนมี 4 ขั้นตอน
- Random ตัวเลขอะไรมาก็ได้จำนวน 12 ตัว โดยมีกฎอยู่ว่า ตัวแรกห้ามเป็นเลข 0 หรือ 9 เช่น 189353534573
- เอาเลข 12 หลักจากข้อแรกมาคูณกับเลข n — index ของมัน แล้วเอามารวมกัน เช่นจากตัวอย่างก็คือ (113) + (812) + (911) + (310) + (59) + (38) + (57) + (36) + (45) + (54) + (73) + (32) ได้ 427
- นำผลลัพธ์จากข้อที่แล้วมา mod หรือหารเอาเศษด้วย 11 เช่น จากตัวอย่างจะได้ 427 mod 11 = 9
- นำ 11 ไปลบกับผลลัพธ์จากข้อที่แล้ว จะได้เลขหลักที่ 13 เช่นของเราคือ 9 ได้ 11–9 = 2
- เราก็จะสุ่มเลขบัตรขึ้นมาได้เป็น 1893535345732
ChatGPT เสกเป็น code shell script ให้หน่อย…
#!/bin/sh
generate_card_number() {
# Step 1: Random ตัวเลขอะไรมาก็ได้จำนวน 12 ตัว โดยมีกฎอยู่ว่า ตัวแรกห้ามเป็นเลข 0 หรือ 9 เช่น 189353534573
random_number=$(shuf -i 200000000000-899999999999 -n 1)
# Step 2: เอาเลข 12 หลักจากข้อแรกมาคูณกับเลข n - index ของมัน แล้วเอามารวมกัน เช่นจากตัวอย่างก็คือ (1*13) + (8*12) + (9*11) + (3*10) + (5*9) + (3*8) + (5*7) + (3*6) + (4*5) + (5*4) + (7*3) + (3*2) ได้ 427
sum=0
for ((i=0; i<12; i++)); do
digit=${random_number:i:1}
position=$((13 - i))
product=$((digit * position))
sum=$((sum + product))
done
# Step 3: นำผลลัพธ์จาก step2 มา mod หรือหารเอาเศษด้วย 11
remainder=$((sum % 11))
# Step 4: นำ 11 ไปลบกับผลลัพธ์จาก stepที่ 3
thirteenth_digit=$((11 - remainder))
# Step 5: นำผลลัพธ์จาก step4มาต่อกับ step1
echo "${random_number}${thirteenth_digit}"
}
generate_card_number
มาลอง run ทดสอบกัน
# Terminal
./thaitools
# output
2792688255096
ตอนนี้เราสามารถ gen เลขบัตรประชาชนได้แล้ว
สร้าง Command
ตาม design ข้องต้นเราเรียกผ่าน command: cardId สำหรับ gen เลขบัตรประชาชน
.....
# Add command cardId
# if param $1 เท่ากับ command name 'cardId'
if [ "$1" == "cardId" ]; then
# เรียก function สำหรับ gen cardId
card_id=$(generate_card_number)
echo $card_id
else
echo "Invalid command."
fi
# Terminal
./thaitools cardId
# output
2635368457988
สร้าง Option
หลังจากเรามี command cardId เราจะเพิ่มความสามารถให้ command ให้มี option เผื่อให้ dynamic มากขั้น
-n
,--num-cards
: ระบุ จำนวน id ที่เราอยากให้ gen-h
,--file
: ระบุ output เป็น file
#!/bin/bash
# Add Command cardId
# if param $1 เท่ากับ command name 'cardId'
if [ "$1" == "cardId" ]; then
num_cards=1 # Default ให้ generating 1 card ถ้าไม่ระบุ -n option
file_path="" # Default ให้ path ไม่มีค่า หรือ ไม่ต้อง write file
# Loop while หา command-line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
# check arguments เท่ากับ option -n --num-cards
-n|--num-cards)
num_cards="$2"
# shift ไป arguments ถัดไป
shift
;;
# check arguments เท่ากับ option -f|--file
-f|--file)
file_path="$2"
# shift ไป arguments ถัดไป
shift
;;
*)
shift
;;
esac
done
# Generate และ display ตามจำนวนของค่า -n หรือ num_cards
for ((i=0; i<num_cards; i++)); do
card_id=$(generate_card_number)
echo "Generated Card Number $((i+1)): $card_id"
# Check file_path ถ้ามีค่าทำ echo
if [ -n "$file_path" ]; then
# echo หรือ write ข้อมูลลง file
echo "$card_id" >> "$file_path"
fi
done
else
echo "Invalid command."
fi
# Terminal
./thaitools cardId -n 10 -f ~/Desktop/card-numbers.txt
# or
./thaitools cardId -n 10
# or
./thaitools cardId -f ~/Desktop/card-numbers.tx
Help
-h
, --help
เป็น option ที่ขาดไม่ได้สำหรับทุกๆ CLI ถ้ารู้อยากรู้ว่ามันใช้งานยังไง dev ทุกคนรู้กันว่าพิม -h ก่อนเป็นอันดับแรก เพราะมันคือ document ของ CLI นั้นๆ นั้นเอง แล้วมันเขียนยังไง ไปดู!!!!
#!/bin/bash
# function สำหรับแสดง help
display_help() {
echo "Usage: $0 cardId [OPTIONS]"
echo "Generate Thai id"
echo "Options:"
echo " -n, --num-cards NUM Specify the number of card id to generate (default is 1)."
echo " -f, --file FILE Specify the file to save the card id"
echo " -h, --help Display this help message."
}
# Add Command cardId
# if arguments $1 เท่ากับ command name 'cardId'
if [ "$1" == "cardId" ]; then
# check arguments $2 เท่ากับ -h|--help
case "$2" in
-h|--help)
display_help
exit 0
;;
esac
num_cards=1 # Default ให้ generating 1 card ถ้าไม่ระบุ -n option
file_path="" # Default ให้ path ไม่มีค่า หรือ ไม่ต้อง write file
.....
else
echo "Invalid command."
display_help
fi
# Terminal
./thaitools cardid -h
#output
Invalid command.
Usage: thaitools cardId [OPTIONS]
Generate Thai id
Options:
-n, --num-cards NUM Specify the number of card id to generate (default is 1).
-f, --file FILE Specify the file to save the card id
-h, --help Display this help message.
วิธี export path
เราอยากให้สามารถเรียกใช้ CLI thaitools ที่เราสร้างขึ้นมาจาก directory ไหนก็ได้
- ตรวจสอบว่า command line tools เราใช่ shell อะไร
# Terminal
echo $SHELL
# output
/bin/bash or /bin/zs
2. เปิด file Dotfile ซึ่งถ้าเป็น /bin/bash ก็จะเป็น file .bash_profile และ /bin/zsh เป็น .zshrc
# Terminal
open -e ~/.zshrc
เป็นคำสั่งเปิด text editor
3. เพิ่ม path ของ thaitools save file และ restart command line tools
มีอีกวิธี คือการย้าย file thaitools ไปอยู่ใน system path ของเครื่องของคุณ
mv thaitools /usr/local/bin
เป็นอันเสร็จวิธี export path
ลองใช้งาน thaitools ของเรากัน
###################### Finish ##########################