နားလည်ထားရမယ့် အချက်
`if`/`elif`/`else`/`fi` block တစ်ခုသည် test expression အောင်မြင်မအောင်မြင်ပေါ်မူတည်ပြီး command မတူညီများ run ပေးသည် — bash တွင် 'အောင်မြင်' ဆိုသည်မှာ အလွန် သီးခြားပြီး ထင်ရာမမှန်နိုင်သော အဓိပ္ပာယ်ရှိသည်: ၎င်းသည် exit status အတိအကျ 0 ဖြစ်ခြင်းသာ ဖြစ်သည်။ ဒါကြောင့် special 'test' construct တစ်ခုတည်းသာမက command မည်သည့်အမျိုးအစားမဆိုကို `if` ၏ condition အဖြစ် သုံးနိုင်ခြင်းဖြစ်သည် — bash က ၎င်းကို run ပြီး exit code ကိုသာ စစ်ပါသည်။ Classic test syntax ဖြစ်သော `[ ]` သည် တကယ်တော့ `test` command ကို bracket ဝတ်ဆင်ထားသည့် ကြေးမုံပုံရိပ်သာဖြစ်ပြီး၊ `[` ကို literal program name အဖြစ်၊ `]` ကို လိုအပ်သော closing argument အဖြစ်ခေါ်ကာ ordinary program တစ်ခုအနေနဲ့ run ခြင်းသာဖြစ်သည် — ဆိုလိုသည်မှာ တခြား command များနည်းတူပင် word-splitting နှင့် globbing အန္တရာယ်ဆီ ကျရောက်နိုင်သဖြင့် ၎င်း၏ argument များကို ဂရုတစိုက် quote လုပ်ရန် လိုအပ်သည် — quote မပါသော empty variable တစ်ခုက `[ $var == value ]` ကို syntax error အဖြစ် ပြောင်းသွားစေနိုင်သည်။ Bash ကိုယ်ပိုင် `[[ ]]` extended test မှာမူ program သီးခြားတစ်ခုမဟုတ်ဘဲ shell keyword တစ်ခုဖြစ်ပြီး၊ ထိုကွာခြားချက်ကပင် ထိုအန္တရာယ်အများစုကို ရှောင်ရှားနိုင်စေသည် — quote မပါသော variable များ ၎င်းအထဲတွင် word-split (သို့) glob မဖြစ်တော့ဘဲ၊ ထို့အပြင် `-a`/`-o` (သို့) bracket အသီးသီး ခွဲရေးရန် မလိုအပ်ဘဲ `&&`၊ `||` နှင့် pattern matching ကို bracket အထဲတွင် တိုက်ရိုက် support လုပ်သည်။ အသုံးများသော test operator များတွင် `-f` (regular file ရှိသလား)၊ `-d` (directory ရှိသလား)၊ `-z` (string ဗလာလား)၊ `-eq` (numeric equality)၊ `==` (string equality) တို့ ပါဝင်ပြီး — numeric နှင့် string comparison ကို ရောထွေးသုံးမိခြင်းသည် beginner များ အများဆုံးလုပ်မိတတ်သော အမှားများထဲမှတစ်ခုဖြစ်သည်၊ အကြောင်းမှာ `-eq` က value နှစ်ခုကို integer အဖြစ် နှိုင်းယှဉ်ပြီး `==` က character တစ်ခုချင်းစီအလိုက် text အဖြစ် နှိုင်းယှဉ်သောကြောင့်ဖြစ်ပြီး၊ ဤနှစ်ခုသည် `[ ]` အတွင်း အဘယ်အခါမျှ အစားထိုးမရနိုင်ပါ။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Config file တစ်ခု ဖတ်မိမီ ရှိမရှိစစ်ရန်၊ numeric setting တစ်ခု threshold တစ်ခုထက် ကျော်မကျော် စစ်ရန် လိုအပ်သော setup script တစ်ခုသည် conditional များ တွေ့ရလေ့ရှိသော နေရာဖြစ်သည် — `if [[ -f "$config" ]] && [[ "$timeout" -gt 30 ]]; then` ကဲ့သို့ file-existence check နှင့် numeric comparison ကို line တစ်ကြောင်းတည်းတွင် ဖတ်ရှုလွယ်စွာ ပေါင်းစပ်နိုင်ပြီး၊ `[[ ]]` ကို သုံးထားခြင်းက `$config` တွင် space ပါသွားခဲ့ရင်တောင် script ပျက်စီးမသွားစေပါ။ Lesson ၏ ဥပမာကိုယ်တိုင်ကလည်း အလားတူ အဆင့်ဆင့် ချဉ်းကပ်ပုံကို ပြသသည် — file ရှိကြောင်း မယုံမီ `-f` ဖြင့် ပထမဆုံး စစ်ဆေးပြီး၊ `-d` နှင့် `-f` ကို `[[ ]]` တစ်ခုတည်းထဲတွင် `&&` ဖြင့် ပေါင်းစပ်ကာ၊ `-z` ဖြင့် empty string ကို ရှာဖွေပြီး၊ နောက်ဆုံးတွင် `"9"` နှင့် `"10"` value များပေါ်တွင် `-lt` (numeric) ကို `[[ ]]` အတွင်းရှိ `>` (lexical string comparison) နှင့် ယှဉ်ကြည့်ပြသထားသည် — operator မှားရွေးလိုက်လျှင် numeric ပုံစံကဲ့သို့ ထင်ရသော comparison တစ်ခုသည် string အဖြေတစ်ခုကို တိတ်တဆိတ် ထုတ်ပေးနိုင်ကြောင်း အတိအကျ ပြသနေပါသည်။
အတူတူ စမ်းရေးကြည့်မယ်
#!/usr/bin/env bash
# Create a sample file and directory to test against
mkdir -p /tmp/bash-lesson-demo
touch /tmp/bash-lesson-demo/sample.txt
file="/tmp/bash-lesson-demo/sample.txt"
dir="/tmp/bash-lesson-demo"
missing="/tmp/bash-lesson-demo/does-not-exist.txt"
if [ -f "$file" ]; then
echo "$file is a regular file"
fi
if [[ -d "$dir" && -f "$file" ]]; then
echo "Both the directory and file exist"
fi
if [ -f "$missing" ]; then
echo "This should not print"
else
echo "$missing does not exist"
fi
name=""
if [ -z "$name" ]; then
echo "name is empty"
fi
count=10
if [ "$count" -eq 10 ]; then
echo "count numerically equals 10"
fi
# The classic string-vs-numeric pitfall
a="9"
b="10"
if [ "$a" -lt "$b" ]; then
echo "$a is numerically less than $b"
fi
if [[ "$a" > "$b" ]]; then
echo "$a sorts after $b as a STRING (misleading if you meant numbers)"
fi
rm -rf /tmp/bash-lesson-demoဤ script ကို run လိုက်လျှင် အောက်ပါအတိုင်း ထွက်ပါမည်:
/tmp/bash-lesson-demo/sample.txt is a regular file
Both the directory and file exist
/tmp/bash-lesson-demo/does-not-exist.txt does not exist
name is empty
count numerically equals 10
9 is numerically less than 10
9 sorts after 10 as a STRING (misleading if you meant numbers)၅ မိနစ် စမ်းကြည့်
မိမိရွေးချယ်သော path တစ်ခုအကြောင်း အချက်သုံးခုကို စစ်ဆေးသော script တစ်ခု ရေးပါ — directory အဖြစ်ရှိမရှိ၊ ၎င်းအတွင်းရှိ file တစ်ခုရှိမရှိ၊ retry count ကိုယ်စားပြုသော numeric variable တစ်ခု သုညထက်ကြီးမကြီး — [[ ]] ကိုသုံးပြီး check တစ်ခုစီအတွက် ရှင်းလင်းသော message print ပါ။
သတိလေးတစ်ချက်
Quote မပါသော variable ဖြင့် [ $var == value ] သုံးရာ variable ဗလာဖြစ်နေခြင်း (သို့) space ပါခြင်းကြောင့် 'unary operator expected' ကဲ့သို့ syntax error ဖြစ်ခြင်း
-eq အစား == ဖြင့် နံပါတ်များ နှိုင်းယှဉ်ခြင်း (သို့) ပြောင်းပြန် string များကို -eq ဖြင့် နှိုင်းယှဉ်ခြင်းက လုံးဝ fail ဖြစ်စေခြင်း (သို့) မှားယွင်းသော အဖြေကို တိတ်တဆိတ် ပေးစေခြင်း
GNU Bash Reference Manual — Bash Conditional Expressions — Bash / Shell Scripting