Thuta Learning
Bash / Shell Scripting
IntermediateDevOps & Toolsbeginner

Parameter Expansion ဖြင့် String Manipulation

ဒီခန်းပြီးရင် ဘာတတ်သွားမလဲ

  • Parameter Expansion ဖြင့် String Manipulation concept ကို နားလည်ရှင်းပြနိုင်ရန်
  • နမူနာ code ကို ကိုယ်တိုင် run ပြီး output စစ်နိုင်ရန်
  • Tutorial Platform project နှင့် production scenario တွင် မှန်ကန်စွာအသုံးချနိုင်ရန်

နားလည်ထားရမယ့် အချက်

Bash တွင် string manipulation အတွက် toolkit တစ်ခုလုံးနီးပါးကို parameter expansion syntax — ${var...} ပုံစံများ — အတွင်းသို့ တိုက်ရိုက် ထည့်သွင်းထားပြီး၊ sed သို့မဟုတ် awk ကို ခေါ်ရမည့် text transformation အများစုကို shell ကိုယ်တိုင်အတွင်းမှာပင် inline လုပ်နိုင်သည်။ ${#str} က string ၏ length ကို ပေးပြီး၊ ${str:offset:length} က substring ကို ဖြတ်ထုတ်ပေးကာ၊ ${str/pattern/replacement} နှင့် ${str//pattern/replacement} တို့က pattern ၏ ပထမ occurrence သို့မဟုတ် occurrence အားလုံးကို အစားထိုးပေးပြီး၊ ${var^^} နှင့် ${var,,} တို့က uppercase သို့မဟုတ် lowercase သို့ ပြောင်းလဲပေးသည်။ trim family — ${var#pattern}, ${var##pattern}, ${var%pattern}, ${var%%pattern} — ကို အထူးဂရုစိုက်ရသည် — ဤအရာသည် axis နှစ်ခု အမှန်တကယ် ဖြစ်နေသောကြောင့်ဖြစ်သည်: # က ရှေ့ဘက်မှ trim လုပ်ပြီး % က နောက်ဘက်မှ trim လုပ်ကာ၊ double form (## သို့မဟုတ် %%) သည် greedy ဖြစ်ပြီး ဖြစ်နိုင်သမျှ အများဆုံး match ဖြစ်စေပြီး single form ကမူ ဖြစ်နိုင်သမျှ အနည်းဆုံးသာ match ဖြစ်စေသည်။ ဤအချက်ကြောင့်ပင် /usr/local/bin/script.sh ကဲ့သို့ slash များစွာပါသော path တစ်ခုတွင် ${path#*/} (ပထမ slash အထိသာ ဖြတ်ထုတ်) နှင့် ${path##*/} (နောက်ဆုံး slash အထိ ဖြတ်ထုတ်ပြီး filename ကိုသာ ကျန်ရစ်စေ) တို့သည် ရလဒ်ကွာခြားနေခြင်းဖြစ်သည်။ ဆက်စပ်သော်လည်း မတူညီသော form တစ်ခုဖြစ်သည့် ${var:-default} နှင့် ${var:?message} တို့မှာ string manipulation နှင့် မဆိုင်ပါ — variable တစ်ခု unset ဖြစ်ကောင်းဖြစ်နိုင်သည့် အခြေအနေကို လုံခြုံစွာ ကိုင်တွယ်ရန်ဖြစ်ပြီး၊ script တစ်ခုကို default value သို့ fallback ခွင့်ပြုနိုင်သလို empty string ဖြင့် တိတ်တဆိတ် ဆက်လက် run နေမည့်အစား error message ရှင်းရှင်းလင်းလင်းဖြင့် ကျယ်ကျယ်လောင်လောင် fail ဖြစ်စေနိုင်သည်။ ဤ operation များသည် separate process တစ်ခုမျှ spawn မလုပ်သောကြောင့် loop အတွင်းမှ external tool ကို ခေါ်ခြင်းထက် သိသိသာသာ ပိုမြန်ဆန်သည်။

လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်

Upload လုပ်လိုက်သော filename များကို process လုပ်ရသော script တစ်ခု ရေးနေသည်ဟု ဆိုကြပါစို့ — file extension ကို ဖြတ်ထုတ်ရန်၊ လိုအပ်သော environment variable ကို ဆက်မလုပ်ခင် သတ်မှတ်ပြီးမပြီး စစ်ဆေးရန်၊ username ကို နှိုင်းယှဉ်ခင် lowercase အဖြစ် normalize လုပ်ရန် လိုအပ်သည် — ဤ lesson ၏ code သည် ဤလို operation များကို အတိအကျ ဖော်ပြထားသည်။ archive.tar.gz မှ .tar.gz extension ကို ဖြတ်ထုတ်ခြင်းက # vs ## / % vs %% ကွာခြားချက်ကို ခိုင်လုံစွာ ပြသသည် — ${filename%.*} သည် နောက်ဆုံးမှ shortest match ကိုသာ ဖယ်ရှားပေးသဖြင့် archive.tar ကျန်ရစ်စေပြီး (.gz ပျောက်သွားသော်လည်း .tar ကျန်နေသည်)၊ ${filename%%.*} ကမူ ပထမ dot မှစ၍ အားလုံးကို greedy စွာ ဖယ်ရှားပေးသဖြင့် archive ကိုသာ ကျန်ရစ်စေသည် — extension တစ်ခုတည်းသာ ရှိသော file ဖြစ်သလား၊ .tar.gz ကဲ့သို့ compound extension ဖြစ်သလားပေါ် မူတည်၍ မည်သည်ကို လိုအပ်သည်ဆိုတာ ကွာခြားသည်။ ဤ logic အတိုင်းပင် ဆန့်ကျင်ဘက် direction ဖြင့် code ထဲရှိ path တွင်လည်း အသုံးချသည် — ${path#*/} သည် ပထမ slash အထိသာ ဖြတ်ထုတ်ပေးပြီး ${path##*/} ကမူ နောက်ဆုံး slash အထိ ဖြတ်ထုတ်ပေးသဖြင့်၊ basename ကို ခေါ်စရာမလိုဘဲ path အပြည့်အစုံမှ bare filename ကို ရယူရန် idiomatic နည်းလမ်းဖြစ်သည်။ လိုအပ်သော variable ကို validate လုပ်ရန်အတွက် ${required_var:?message} သည် ${greeting:-Hi there} ထက် တမင် ပို၍ aggressive ဖြစ်သည် — fallback value ကို တိတ်တဆိတ် အစားထိုးမည့်အစား variable unset ဖြစ်နေလျှင် သို့မဟုတ် empty ဖြစ်နေလျှင် error message ဖြင့် abort ဖြစ်စေသည်; ၎င်းသည် caller က သတ်မှတ်ပေးထားရမည့် variable တစ်ခုနှင့် destructive တစ်ခုခု မလုပ်ဆောင်မီ script ၏ အစတွင် ရှိသင့်သော behavior အတိအကျပင် ဖြစ်သည်။

အတူတူ စမ်းရေးကြည့်မယ်

bash
#!/bin/bash
str="Hello, Bash World"
echo "Length: ${#str}"
echo "Substring: ${str:7:4}"
echo "Replace first: ${str/Bash/Shell}"
echo "Replace all: ${str//o/0}"

filename="archive.tar.gz"
echo "Remove shortest suffix: ${filename%.*}"
echo "Remove longest suffix: ${filename%%.*}"

path="/usr/local/bin/script.sh"
echo "Remove shortest prefix: ${path#*/}"
echo "Remove longest prefix: ${path##*/}"

unset greeting
echo "Default value: ${greeting:-Hi there}"

# ${var:?message} exits with an error if the variable is unset or empty
unset required_var
if (: "${required_var:?required_var must be set}") 2>/dev/null; then
  echo "required_var is set"
else
  echo "Caught missing variable error"
fi

name="bash"
echo "Uppercase: ${name^^}"
echo "Lowercase: ${name,,}"
You should see
ဤ script ကို run လိုက်လျှင် အောက်ပါအတိုင်း output ရရှိမည်−

Length: 17
Substring: Bash
Replace first: Hello, Shell World
Replace all: Hell0, Bash W0rld
Remove shortest suffix: archive.tar
Remove longest suffix: archive
Remove shortest prefix: usr/local/bin/script.sh
Remove longest prefix: script.sh
Default value: Hi there
Caught missing variable error
Uppercase: BASH
Lowercase: bash

၅ မိနစ် စမ်းကြည့်

/home/user/photos/vacation.jpg ကဲ့သို့ file path အပြည့်အစုံ ပါဝင်သော variable တစ်ခုပေးထားလျှင်၊ parameter expansion သာသုံး၍ (external command မသုံးဘဲ) directory မပါသော filename ကိုသာ print ထုတ်ပြီး၊ filename မပါသော extension ကိုသာ သီးခြား print ထုတ်ပါ။

သတိလေးတစ်ချက်

# (front မှ shortest match) နှင့် ## (front မှ longest match) ကို ရောထွေးခြင်း — slash များစွာပါသော path တစ်ခုတွင် ${path#*/} နှင့် ${path##*/} က ရလဒ်များစွာကွာခြားသည်

${var/pattern/replacement} သည် ပထမတွေ့သော occurrence တစ်ခုကိုသာ အစားထိုးကြောင်း မေ့လျော့ခြင်း — occurrence အားလုံးကို အစားထိုးရန် // ကိုသုံးရမည်

GNU Bash Manual: Shell Parameter ExpansionBash / Shell Scripting

ဒီနေရာမှာ လူအများမှားတတ်တယ်

  • # (front မှ shortest match) နှင့် ## (front မှ longest match) ကို ရောထွေးခြင်း — slash များစွာပါသော path တစ်ခုတွင် ${path#*/} နှင့် ${path##*/} က ရလဒ်များစွာကွာခြားသည်
  • ${var/pattern/replacement} သည် ပထမတွေ့သော occurrence တစ်ခုကိုသာ အစားထိုးကြောင်း မေ့လျော့ခြင်း — occurrence အားလုံးကို အစားထိုးရန် // ကိုသုံးရမည်
  • နမူနာ code ကို production system ပေါ် တိုက်ရိုက်မစမ်းဘဲ local/test environment တွင် အရင်အတည်ပြုပါ။

လေ့ကျင့်ခန်း

/home/user/photos/vacation.jpg ကဲ့သို့ file path အပြည့်အစုံ ပါဝင်သော variable တစ်ခုပေးထားလျှင်၊ parameter expansion သာသုံး၍ (external command မသုံးဘဲ) directory မပါသော filename ကိုသာ print ထုတ်ပြီး၊ filename မပါသော extension ကိုသာ သီးခြား print ထုတ်ပါ။

You'll know it worked when: ဤ script ကို run လိုက်လျှင် အောက်ပါအတိုင်း output ရရှိမည်− Length: 17 Substring: Bash Replace first: Hello, Shell World Replace all: Hell0, Bash W0rld Remove shortest suffix: archive.tar Remove longest suffix: archive Remove shortest prefix: usr/local/bin/script.sh Remove longest prefix: script.sh Default value: Hi there Caught missing variable error Uppercase: BASH Lowercase: bash

Parameter Expansion ဖြင့် String Manipulation | Thuta Learning