နားလည်ထားရမယ့် အချက်
Script ကို `./greet.sh alice bob` ကဲ့သို့ argument များနှင့် run လိုက်လျှင် bash က ၎င်းတို့ကို script ထဲတွင် positional parameter များအဖြစ် ရရှိစေသည် — `$1` သည် ပထမ argument၊ `$2` သည် ဒုတိယ argument ဖြစ်ပြီး `$9` အထိ ဆက်လက် သွားနိုင်သည် (ထိုထက်ကျော်လျှင် `${10}` ကဲ့သို့ brace ဖြင့် ရေးရမည်ဖြစ်သည်၊ အကြောင်းမှာ `$10` ဟု ရေးလိုက်လျှင် `$1` နောက်တွင် literal `0` တစ်ခု ဆက်နေသည်ဟု bash က parse လုပ်ပစ်မည်ဖြစ်သောကြောင့်ဖြစ်သည်)၊ `$#` က စုစုပေါင်း argument ဘယ်နှစ်ခု ပေးပို့ခဲ့သလဲ ပြောပြသည်။ `$@` နှင့် `$*` နှစ်ခုလုံးက 'argument အားလုံး' ကို ကိုယ်စားပြုသည်ဟု အမည်ခံထားသော်လည်း quote ပါ/မပါအလိုက် အလွန် ကွဲပြားသွားသည်။ Quote မပါလျှင် နှစ်ခုစလုံး တူညီစွာ word split ဖြစ်ပြီး internal structure ဆုံးရှုံးသွားသည်။ Quote ပါလျှင်မူ လုံးဝကွဲပြားသည် — `"$@"` သည် argument တစ်ခုချင်းစီကို space ပါသည့်တိုင် သီးခြား word အဖြစ် မှန်ကန်စွာ ထိန်းထားပါ expand ဖြစ်ပြီး၊ `"$*"` က argument အားလုံးကို `$IFS` ၏ ပထမ character (default အနေနဲ့ space) ဖြင့် ချိတ်ကာ string တစ်ခုတည်းအဖြစ် ပေါင်းလိုက်သည်။ ဒါကြောင့် argument များပေါ် တစ်ခုချင်း loop လုပ်တဲ့အခါ `"$@"` က ဂိုးဂိတ် မှန်ကန်တဲ့ ရွေးချယ်မှုဖြစ်ပါတယ်။ ကြိုတင်ပေးထားသော argument အစား interactive input အတွက် `read` builtin က script ကို ခေတ္တရပ်ပြီး ရိုက်ထည့် (သို့) pipe ဖြင့်ပေးလိုက်သော line တစ်ကြောင်းကို variable ထဲ သိမ်းပေးသည်၊ ၎င်းက script တစ်ခုကို user ကို interactive ဖြင့် တောင်းခံနိုင်စေသည်။ Argument နှင့် variable များသည် optional ဖြစ်ခဏခဏရှိတတ်သောကြောင့် `${1:-default}` expansion pattern က argument (သို့) variable မသတ်မှတ်ရှိ (သို့) empty ဖြစ်နေလျှင် fallback value တစ်ခု ပေးပြီး script crash မဖြစ်စေဘဲ empty string ကို တိတ်တဆိတ် အသုံးမပြုမိစေပါ။
လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
Backup script တစ်ခုသည် target directory ကို ပထမ argument အဖြစ် လက်ခံနိုင်ပြီး user က မပေးလျှင် သင့်လျော်သော default တန်ဖိုးသို့ ပြန်သွားနိုင်သည် — `target=${1:-/var/backups}` ဟု ရေးထားလျှင် argument သုညခုဖြင့် ခေါ်လိုက်လျှင်ပင် script က မှန်ကန်စွာ ဆက်အလုပ်လုပ်ပါလိမ့်မည်။ ယခု ထိုစ script တစ်ခုတည်းက space ပါသော filename များစာရင်းကို နောက်ထပ် argument များအဖြစ် လက်ခံပြီး loop လုပ်ရသေးသည်ဆိုပါစို့ — lesson ၏ ဥပမာထဲကလိုပင် `"charlie brown"` ကဲ့သို့ space ပါသော argument ရှိလျှင်။ Quote မပါသော `$*` (သို့) quote ပါသော `"$*"` ဖြင့် loop လုပ်လိုက်လျှင် အားလုံးကို အပိုင်းအစများ (သို့) ချိတ်ဆက်ထားသော string တစ်ခုတည်းအဖြစ် ဖြိုချလိုက်ပြီး၊ `"charlie brown"` ကို `charlie` နှင့် `brown` ဟု word နှစ်ခုအဖြစ် ခွဲသွားမှာဖြစ်ကြောင်း ဥပမာ output ကိုယ်တိုင်က ပြသနေသည်။ Quote ပါသော `"$@"` ဖြင့် loop လုပ်လိုက်လျှင်မူ argument မူရင်းတစ်ခုစီကို မပျက်စီးအောင် ထိန်းထားပေးသဖြင့် `"charlie brown"` သည် item တစ်ခုတည်းအနေနဲ့သာ ကျန်ရှိနေမည်ဖြစ်သည်။ Read အတွက်လည်း ဒီအတူတူပင် သတိပြုရသည် — line တစ်ကြောင်းကို variable ထဲ ဖမ်းယူပြီးနောက် ၎င်းကို quote မပါဘဲ နောက်တွင် သုံးလိုက်ခြင်းက ယခင် lesson တွင် ပြောခဲ့ပြီးသော word-splitting အန္တရာယ်ကို ပြန်လည် ခေါ်ဆောင်လာနိုင်သည်။
အတူတူ စမ်းရေးကြည့်မယ်
#!/usr/bin/env bash
# Simulate command-line arguments using "set --" (in real use these
# would come from: ./script.sh alice bob "charlie brown")
set -- alice bob "charlie brown"
echo "Argument count: $#"
echo "First argument: $1"
echo "Second argument: $2"
echo 'Looping with unquoted $*:'
for name in $*; do
echo " name -> $name"
done
echo 'Looping with quoted "$@":'
for name in "$@"; do
echo " name -> $name"
done
echo "Enter your favorite language:"
read -r favorite <<< "bash"
echo "You picked: $favorite"
greeting=${4:-"stranger"}
echo "Hello, $greeting"ဤ script ကို run လိုက်လျှင် အောက်ပါအတိုင်း ထွက်ပါမည်:
Argument count: 3
First argument: alice
Second argument: bob
Looping with unquoted $*:
name -> alice
name -> bob
name -> charlie
name -> brown
Looping with quoted "$@":
name -> alice
name -> bob
name -> charlie brown
Enter your favorite language:
You picked: bash
Hello, stranger၅ မိနစ် စမ်းကြည့်
အရောင်များကို ကိုယ်စားပြုသော argument သုံးခုကို simulate လုပ်ရန် `set -- ...` သုံးသော script တစ်ခု ရေးပါ၊ `$#` ဖြင့် argument ဘယ်နှစ်ခုရှိလဲ print လုပ်ပါ၊ ပြီးလျှင် quote မပါသော `$*` တစ်ကြိမ်နှင့် quote ပါသော `"$@"` တစ်ကြိမ် — space ပါသော အရောင်အမည် (ဥပမာ 'light blue') ကို သုံးပြီး ကွာခြားချက်ကို ကြည့်ရန် နှစ်ကြိမ် loop လုပ်ပါ။
သတိလေးတစ်ချက်
$@ (သို့) $* ကို quote မပါဘဲ loop လုပ်ခြင်း (သို့) $@ အစား $* ကို quote လုပ်ခြင်းကြောင့် space ပါသော argument များ တိတ်တဆိတ် အပိုင်းများအဖြစ် ကွဲသွားခြင်း
$1 ရှိမည်ဟု default (သို့) check မလုပ်ဘဲ ယူဆထားခြင်းကြောင့် caller က argument ပေးရန်မေ့ချိန် script crash ဖြစ်ခြင်း (သို့) empty string ဖြင့် ထူးဆန်းစွာ ပြုမူခြင်း
GNU Bash Reference Manual — Special Parameters — Bash / Shell Scripting