ဒေတာ ပြုပြင်စီမံခြင်း (Data Wrangling)
သင့်ထံတွင် စာသား (text) များစွာရှိပြီး ယင်းတို့ဖြင့် တစ်စုံတစ်ခု ပြုလုပ်လိုသည့် အခြေအနေမျိုး ကြုံတွေ့ဖူးပါသလား။ အဆင်ပြေပါသည်။ ထိုသို့ ပြုလုပ်ခြင်းသည် Data Wrangling (ဒေတာ ပြုပြင်ပြင်ဆင်ခြင်း) ၏ အဓိက သဘောတရားပင် ဖြစ်ပါသည်။ အတိအကျ ပြောရလျှင် ဒေတာများကို မိမိ လိုချင်သော ပုံစံအတိုင်း အတိအကျ ရရှိသည်အထိ Format တစ်ခုမှ အခြား Format တစ်ခုသို့ ပြောင်းလဲ ပြုပြင်ခြင်း ဖြစ်ပါသည်။
ကျွန်ုပ်တို့သည် အခြေခံ Data Wrangling ကို တွေ့မြင်ခဲ့ကြပြီး ဖြစ်သည်- journalctl | grep -i intel။
- Intel ဟု ပါဝင်သော စနစ် Log ထည့်သွင်းချက်များ အားလုံးကို ရှာဖွေပေးသည် (စာလုံးကြီး/စာလုံးသေး မခွဲခြားပါ - case-insensitive)
- အမှန်တော့ Data Wrangling ၏ အဓိက အစိတ်အပိုင်းမှာ မိမိထံတွင် မည်သည့် tool များ ရှိသည်နှင့် ယင်းတို့ကို မည်သို့ ပေါင်းစပ် အသုံးပြုရမည်ကို သိရှိထားခြင်း ဖြစ်ပါသည်။
အစမှ စတင်ကြည့်ကြပါစို့- ကျွန်ုပ်တို့တွင် ဒေတာ အရင်းအမြစ် (data source) တစ်ခုနှင့် ယင်းဒေတာဖြင့် ပြုလုပ်လိုသည့် အရာတစ်ခု လိုအပ်ပါသည်။ Log ဖိုင်များသည် အလွန် ကောင်းမွန်သော စံနမူနာ ဖြစ်ပါသည်၊ အကြောင်းမှာ Log များအကြောင်းကို လေ့လာ စုံစမ်းရန် လိုအပ်သော်လည်း ဖိုင်တစ်ခုလုံးကို ဖတ်ရှုရန် မဖြစ်နိုင်သောကြောင့် ဖြစ်ပါသည်။ အောက်ပါ Server log ကို ကြည့်၍ ကျွန်ုပ်၏ Server ထံသို့ မည်သူက Log in ဝင်ရန် ကြိုးစားနေသည်ကို လေ့လာကြည့်ကြပါစို့-
ssh myserver journalctl
ဤသည်မှာ အချက်အလက်များ လွန်စွာ များပြားလှပါသည်။ သို့ဖြစ်၍ SSH နှင့် သက်ဆိုင်သည်များကိုသာ ခွဲထုတ်ကြည့်ကြမည်-
ssh myserver journalctl | grep sshd
ဒီနေရာတွင် Pipe ကို အသုံးပြု၍ Remote (အဝေးထိန်း) ဖိုင်ကို မိမိ စက်ပေါ်ရှိ grep ထံသို့ Stream ပြုလုပ် ပေးပို့ထားသည်ကို သတိပြုပါ။ ssh သည် အလွန် အသုံးဝင်ဆန်းကြယ်လှပါသည်။ သို့သော် ဤသည်မှာလည်း ကျွန်ုပ်တို့ လိုချင်သည်ထက် အချက်အလက်များ များပြားနေပါသေးသည်။ ထို့အပြင် ဖတ်ရှုရန်လည်း ခက်ခဲပါသည်။ ပိုမို ကောင်းမွန်အောင် ပြုလုပ်ကြပါစို့-
ssh myserver journalctl | grep sshd | grep "Disconnected from"
ဤနေရာတွင် မလိုအပ်သော အချက်အလက်များ (noise) များစွာ ပါဝင်နေသေးသည်။ ယင်းတို့ကို ဖယ်ရှားရန် နည်းလမ်းများ စွာ ရှိသော်လည်း သင်၏ Toolkit ထဲမှ စွမ်းအားအရှိဆုံး Tool တွေထဲက တစ်ခုဖြစ်သည့် sed ကို လေ့လာကြည့်ကြပါစို့။
sed သည် ရှေးယခင် ed editor ပေါ်တွင် အခြေခံ၍ ပြုလုပ်ထားသော “Stream Editor” တစ်ခု ဖြစ်ပါသည်။ ၎င်းတွင် ဖိုင်၏ အကြောင်းအရာများကို တိုက်ရိုက် ပြင်ဆင်ခြင်းထက် (တိုက်ရိုက် ပြင်ဆင်၍လည်း ရသော်လည်း) ဖိုင်ကို မည်သို့ ပြင်ဆင်ရမည်ဆိုသည့် Command တိုများကို ပေးပို့ရခြင်း ဖြစ်ပါသည်။ Command များစွာ ရှိသည့်အနက် အသုံးအများဆုံး တစ်ခုမှာ s (Substitution - အစားထိုးခြင်း) ဖြစ်ပါသည်။ ဥပမာ- အောက်ပါအတိုင်း ရေးသားနိုင်ပါသည်-
ssh myserver journalctl
| grep sshd
| grep "Disconnected from"
| sed 's/.*Disconnected from //'
ယခုလေးတင် ရေးသားလိုက်သည်မှာ ရိုးရှင်းသော Regular Expression ဖြစ်ပါသည်။ ၎င်းသည် Pattern များနှင့် စာသားများကို တိုက်ဆိုင်စစ်ဆေး (match) ပေးနိုင်သော စွမ်းအားထက်သည့် နည်းလမ်းတစ်ခု ဖြစ်ပါသည်။ s command ကို s/REGEX/SUBSTITUTION/ ပုံစံဖြင့် ရေးသားပြီး REGEX သည် သင်ရှာဖွေလိုသော Regular Expression ဖြစ်ကာ SUBSTITUTION သည် ကိုက်ညီသော စာသားနေရာတွင် အစားထိုးလိုသည့် စာသား ဖြစ်ပါသည်။
Regular expressions
Regular expression များသည် အသုံးများပြီး အလွန် အသုံးဝင်သောကြောင့် ၎င်းတို့ မည်သို့ အလုပ်လုပ်သည်ကို အချိန်ပေး၍ နားလည်သဘောပေါက်အောင် လေ့လာသင့်ပါသည်။ အထက်တွင် ကျွန်ုပ်တို့ အသုံးပြုခဲ့သည့် /.*Disconnected from / ကို စတင်ကြည့်ကြပါစို့။ Regular expression များကို ပုံမှန်အားဖြင့် (အမြဲတမ်း တော့ မဟုတ်ပါ) / ဖြင့် ဝန်းရံလေ့ ရှိကြသည်။ ASCII စာလုံး အများစုသည် ၎င်းတို့၏ ပုံမှန် အဓိပ္ပာယ်အတိုင်း သက်ရောက်သော်လည်း အချို့သော စာလုံးများသည် “အထူး” ကိုက်ညီမှု ပြုမူဆောင်ရွက်ချက်များ (special matching behavior) ရှိကြသည်။ မည်သည့် စာလုံးက မည်သို့ ပြုလုပ်သည်ဆိုသည်မှာ Regular Expression တည်ဆောက်ပုံ အကောင်အထည်ဖော်မှု (implementation) များအပေါ် မူတည်၍ အနည်းငယ် ကွဲပြားကြပြီး ယင်းသည် အလွန် ရှုပ်ထွေးစိတ်ပျက်စရာ ကောင်းလှပါသည်။ အသုံးများသော Pattern အချို့မှာ အောက်ပါအတိုင်း ဖြစ်သည်-
.သည် Newline မှအပါအဝင် “မည်သည့် စာလုံးတစ်လုံးမဆို” ကို အဓိပ္ပာယ်ရသည်*ရှေ့မှ စာလုံး သို့မဟုတ် Pattern ၀ ခု သို့မဟုတ် ၀ ခုထက်ပို၍ ပါဝင်ခြင်း+ရှေ့မှ စာလုံး သို့မဟုတ် Pattern ၁ ခု သို့မဟုတ် ၁ ခုထက်ပို၍ ပါဝင်ခြင်း[abc]a၊bသို့မဟုတ်cစာလုံးများအနက် မည်သည့် စာလုံးတစ်လုံးမဆို(RX1|RX2)RX1သို့မဟုတ်RX2နှင့် ကိုက်ညီသည့် အရာတစ်ခုခု^စာကြောင်း၏ အစ$စာကြောင်း၏ အဆုံး
sed ၏ Regular Expression များသည် အနည်းငယ် ထူးဆန်းပြီး အထူး အဓိပ္ပာယ် သက်ရောက်စေရန် ၎င်းတို့၏ ရှေ့တွင် \ ထည့်သွင်းပေးရန် လိုအပ်ပါသည်။ သို့မဟုတ်ပါက -E flag ကို သုံးနိုင်ပါသည်။
ထို့ကြောင့် /.*Disconnected from / ကို ပြန်လည်ကြည့်ရှုပါက ၎င်းသည် မည်သည့် စာလုံး အရေအတွက်မဆို ပါဝင်ပြီး ၎င်းနောက်တွင် “Disconnected from “ ဟူသည့် စာသား အတိအကျ ပါဝင်သော မည်သည့် စာသားမဆိုနှင့် ကိုက်ညီမှု ရှိသည်ကို တွေ့ရမည် ဖြစ်ပါသည်။ ဤသည်မှာ ကျွန်ုပ်တို့ လိုချင်သည့် အရာ ဖြစ်သည်။ သို့သော် သတိပြုပါ၊ Regular Expression များသည် ရှုပ်ထွေးလှပါသည်။ အကယ်၍ တစ်စုံတစ်ယောက်က “Disconnected from” ဟူသော Username ဖြင့် Log in ဝင်ရန် ကြိုးစားခဲ့ပါက မည်သို့ ဖြစ်မည်နည်း။ အောက်ပါအတိုင်း ရှိနေမည် ဖြစ်သည်-
Jan 17 03:13:00 thesquareplanet.com sshd[2631]: Disconnected from invalid user Disconnected from 46.97.239.16 port 55920 [preauth]
ကျွန်ုပ်တို့ မည်သည့် ရလဒ် ရရှိမည်နည်း။ အမှန်တော့ * နှင့် + တို့သည် ပုံမှန်အားဖြင့် “Greedy” (ဝါးမျိုသော/အတတ်နိုင်ဆုံး အများဆုံး ယူသော) သဘောရှိကြသည်။ ၎င်းတို့သည် တတ်နိုင်သမျှ စာသား အရေအတွက် အများဆုံးနှင့် ကိုက်ညီအောင် ပြုလုပ်ကြသည်။ သို့ဖြစ်၍ အထက်ပါ ဥပမာတွင် အောက်ပါအတိုင်းသာ ကျန်ရစ်မည် ဖြစ်သည်-
46.97.239.16 port 55920 [preauth]
ယင်းသည် ကျွန်ုပ်တို့ လိုချင်သော ရလဒ် ဟုတ်ချင်မှ ဟုတ်ပေလိမ့်မည်။ Regular Expression Implementation အချို့တွင် * သို့မဟုတ် + ၏ အနောက်တွင် ? ထည့်သွင်းခြင်းဖြင့် Non-greedy (အနည်းဆုံးသာ ယူသော) ပုံစံသို့ ပြောင်းလဲနိုင်သော်လည်း စိတ်ပျက်စရာကောင်းသည်မှာ sed က ယင်းကို မပံ့ပိုးပါ။ သို့သော် ယင်းကို ပံ့ပိုးပေးသည့် Perl ၏ Command-line mode သို့ ပြောင်းလဲ အသုံးပြုနိုင်ပါသည်-
perl -pe 's/.*?Disconnected from //'
သို့သော် ဤကဲ့သို့သော လုပ်ဆောင်ချက်များအတွက် sed သည် ပိုမို အသုံးများသော Tool ဖြစ်သောကြောင့် ကျန်ရှိသည့် အပိုင်းများတွင် sed ကိုသာ ဆက်လက် အသုံးပြုသွားမည် ဖြစ်ပါသည်။ sed သည် ကိုက်ညီသော စာကြောင်းများ၏ နောက်ဆက်တွဲ စာကြောင်းများကို ရိုက်နှိပ်ခြင်း၊ Command တစ်ခုတည်းတွင် အစားထိုးမှု အများအပြား ပြုလုပ်ခြင်း၊ အရာဝတ္ထုများ ရှာဖွေခြင်း အစရှိသော အသုံးဝင်သည့် အခြား လုပ်ဆောင်ချက်များကိုလည်း ပြုလုပ်နိုင်ပါသည်။ သို့သော် ဤနေရာတွင် ယင်းတို့ကို အသေးစိတ် ဖော်ပြသွားမည် မဟုတ်ပါ။ sed သည် သီးခြား သီးသန့် လေ့လာရမည့် ခေါင်းစဉ်တစ်ခု ဖြစ်သော်လည်း ၎င်းထက် ပိုမို ကောင်းမွန်သည့် Tool များလည်း ရှိလေ့ ရှိပါသည်။
ကောင်းပါပြီ၊ ထို့ကြောင့် ကျွန်ုပ်တို့ထံတွင် ဖယ်ရှားလိုသော Suffix (အနောက်ဆက်) တစ်ခုလည်း ရှိနေပါသည်။ ၎င်းကို မည်သို့ ဖယ်ရှားနိုင်မည်နည်း။ အထူးသဖြင့် Username တွင် space များ ပါဝင်နိုင်သည့်အတွက် Username ၏ အနောက်မှ စာသားများကိုသာ သီးသန့် တိုက်ဆိုင်စစ်ဆေးရန် အနည်းငယ် ခက်ခဲပါသည်။ ကျွန်ုပ်တို့ ပြုလုပ်ရန် လိုအပ်သည်မှာ စာကြောင်း တစ်ကြောင်းလုံး ကို တိုက်ဆိုင်စစ်ဆေးရန် ဖြစ်သည်-
| sed -E 's/.*Disconnected from (invalid |authenticating )?user .* [^ ]+ port [0-9]+( \[preauth\])?$//'
regex debugger ဖြင့် မည်သို့ အလုပ်လုပ်သည်ကို ကြည့်ရှုကြပါစို့။ အစပိုင်းသည် ယခင်အတိုင်းပင် ဖြစ်ပါသည်။ ထို့နောက် “user” ရှေ့ဆက် အမျိုးအစားများ (Log များတွင် ရှေ့ဆက် ပုံစံ နှစ်ခု ရှိသည်) နှင့် တိုက်ဆိုင် စစ်ဆေးပါသည်။ ထို့နောက် Username ရှိသည့် စာလုံး တန်းစီမှုနှင့် တိုက်ဆိုင် စစ်ဆေးပါသည်။ ထို့နောက် စကားလုံး တစ်လုံးတည်း ([^ ]+; space မဟုတ်သော စာလုံးများ၏ သဲသဲမဲမဲ အစီအစဉ်) နှင့် တိုက်ဆိုင် စစ်ဆေးပါသည်။ ထို့နောက် “port” စကားလုံးနှင့် ယင်းနောက်တွင် ဂဏန်းစဉ် အစီအစဉ် ပါဝင်ပါသည်။ ထို့နောက် ဖြစ်နိုင်ဖွယ်ရှိသော ` [preauth]` အနောက်ဆက် ပါဝင်ပြီး စာကြောင်း၏ အဆုံး သို့ ရောက်ရှိပါသည်။
ဤနည်းလမ်းကို အသုံးပြုခြင်းဖြင့် “Disconnected from” ဟူသော Username သည် ကျွန်ုပ်တို့အား ထပ်မံ ရှုပ်ထွေးစေမည် မဟုတ်သည်ကို သတိပြုပါ၊ အဘယ်ကြောင့်နည်းဆိုသည်ကို မြင်တွေ့နိုင်ပါသလား။
သို့သော် ဤနေရာတွင် ပြဿနာတစ်ခု ရှိသည်၊ ယင်းမှာ Log စာကြောင်း တစ်ခုလုံး ကွက်လပ် ဖြစ်သွားခြင်း ဖြစ်ပါသည်။ အမှန်တော့ ကျွန်ုပ်တို့သည် Username ကို သိမ်းဆည်းထားလိုခြင်း ဖြစ်သည်။ ဤအတွက် “Capture Groups” များကို အသုံးပြုနိုင်ပါသည်။ ကွင်းစကွင်းပိတ် (parentheses) များဖြင့် ဝန်းရံထားသော Regex ဖြင့် တိုက်ဆိုင်စစ်ဆေးမိသော မည်သည့် စာသားမဆိုကို နံပါတ်တပ်ထားသော Capture Group အဖြစ် သိမ်းဆည်းပေးပါသည်။ ယင်းတို့ကို အစားထိုးခြင်း နေရာတွင် \1၊ \2၊ \3 အစရှိသည်ဖြင့် ရရှိ အသုံးပြုနိုင်ပါသည် (အချို့ Engine များတွင် Pattern အတွင်း၌ပင် အသုံးပြုနိုင်သည်)။ သို့ဖြစ်၍-
| sed -E 's/.*Disconnected from (invalid |authenticating )?user (.*) [^ ]+ port [0-9]+( \[preauth\])?$/\2/'
သင် ခန့်မှန်းမိသည့်အတိုင်း လွန်စွာ ရှုပ်ထွေးသော Regular Expression များကို ရေးသားနိုင်ပါသည်။ ဥပမာအားဖြင့် e-mail address များကို မည်သို့ တိုက်ဆိုင်စစ်ဆေးနိုင်ကြောင်း ရေးသားထားသော ဆောင်းပါးကို ကြည့်ပါ။ ယင်းမှာ မလွယ်ကူပါ။ ဆွေးနွေးငြင်းခုံမှုများစွာ လည်း ရှိပါသည်။ ထို့အပြင် Test များ ရေးသားခြင်း၊ Test matrices များ ပြုလုပ်ခြင်း စသည်တို့ ရှိကြပါသည်။ ပေးထားသော ကိန်းဂဏန်းတစ်ခုသည် သဘာဝကိန်း (Prime number) ဟုတ်မဟုတ် စစ်ဆေးနိုင်သည့် Regex ကိုပင် ရေးသားနိုင်ပါသည်။
Regular expression များသည် အမှန်အတိုင်း ရရှိအောင် ပြုလုပ်ရန် ခက်ခဲလွန်းသည်ဟု နာမည်ကြီးသော်လည်း သင်၏ Toolkit တွင် ရှိထားပါက အလွန် အသုံးဝင်သော နည်းလမ်း ဖြစ်ပါသည်။
Back to data wrangling
ကောင်းပြီ၊ ထို့ကြောင့် ယခု ကျွန်ုပ်တို့ထံတွင် အောက်ပါအတိုင်း ရရှိထားသည်-
ssh myserver journalctl
| grep sshd
| grep "Disconnected from"
| sed -E 's/.*Disconnected from (invalid |authenticating )?user (.*) [^ ]+ port [0-9]+( \[preauth\])?$/\2/'
ကျွန်ုပ်တို့သည် sed တစ်ခုတည်းဖြင့်လည်း ပြုလုပ်နိုင်ပါသည်၊ သို့သော် အဘယ်ကြောင့် ပြုလုပ်မည်နည်း။ ပျော်စရာ ကောင်းသောကြောင့် ဖြစ်ပါသည်။
ssh myserver journalctl
| sed -E
-e '/Disconnected from/!d'
-e 's/.*Disconnected from (invalid |authenticating )?user (.*) [^ ]+ port [0-9]+( \[preauth\])?$/\2/'
ဤသည်မှာ sed ၏ စွမ်းဆောင်ရည် အချို့ကို ဖော်ပြနေခြင်း ဖြစ်ပါသည်။ sed သည် စာသားများ ထည့်သွင်းခြင်း (i command ဖြင့်)၊ စာကြောင်းများကို အတိအကျ ထုတ်ပြခြင်း (p command ဖြင့်)၊ အညွှန်း (index) အလိုက် စာကြောင်းများ ရွေးချယ်ခြင်းနှင့် အခြား အရာများစွာကို ပြုလုပ်နိုင်ပါသည်။ man sed တွင် ကြည့်ရှုပါ!
မည်သို့ပင်ဖြစ်စေ၊ ယခု ကျွန်ုပ်တို့ ရရှိထားသည်မှာ Log in ဝင်ရန် ကြိုးပမ်းခဲ့သည့် Username များ အားလုံး၏ စာရင်း ဖြစ်ပါသည်။ သို့သော် ဤသည်မှာ သိပ်ပြီး အသုံးမဝင်လှပါ။ အသုံးအများဆုံး Username များကို ရှာဖွေကြည့်ကြပါစို့-
ssh myserver journalctl
| grep sshd
| grep "Disconnected from"
| sed -E 's/.*Disconnected from (invalid |authenticating )?user (.*) [^ ]+ port [0-9]+( \[preauth\])?$/\2/'
| sort | uniq -c
sort သည် ယင်း၏ Input ကို စီပေးမည် ဖြစ်ပါသည်။ uniq -c သည် တူညီသော ဆက်တိုက် စာကြောင်းများကို စာကြောင်း တစ်ကြောင်းတည်းအဖြစ် ပေါင်းစည်းပေးပြီး ၎င်းတို့ ပါဝင်သည့် အကြိမ်အရေအတွက် Count ကို ရှေ့မှ ထည့်သွင်းပေးသည်။ ယင်းကိုလည်း ထပ်မံ Sort ပြုလုပ်ပြီး အသုံးအများဆုံး Login များကိုသာ ချန်ထားလိုပေလိမ့်မည်-
ssh myserver journalctl
| grep sshd
| grep "Disconnected from"
| sed -E 's/.*Disconnected from (invalid |authenticating )?user (.*) [^ ]+ port [0-9]+( \[preauth\])?$/\2/'
| sort | uniq -c
| sort -nk1,1 | tail -n10
sort -n သည် (အက္ခရာစဉ် မဟုတ်ဘဲ) ကိန်းဂဏန်း အစဉ်အတိုင်း စီပေးမည် ဖြစ်သည်။ -k1,1 ၏ အဓိပ္ပာယ်မှာ “Whitespace ဖြင့် ခွဲခြားထားသော ပထမဆုံး Column ကိုသာ စီရန်” ဖြစ်ပါသည်။ ,n အပိုင်းသည် n ခုမြောက် Field အထိ စီရန် ပြောခြင်းဖြစ်ပြီး ပုံမှန်အတိုင်းဆိုလျှင် စာကြောင်း၏ အဆုံးအထိ ဖြစ်ပါသည်။ ဤ သီးသန့် ဥပမာတွင် စာကြောင်း တစ်ကြောင်းလုံးအလိုက် စီခြင်းသည် ကွဲပြားမှု ရှိမည် မဟုတ်သော်လည်း ကျွန်ုပ်တို့သည် သင်ယူရန် ဤနေရာသို့ ရောက်ရှိနေခြင်း ဖြစ်ပါသည်။
အကယ်၍ ကျွန်ုပ်တို့သည် အသုံး အနည်းဆုံး အရာများကို လိုချင်ပါက tail အစား head ကို အသုံးပြုနိုင်ပါသည်။ ပြောင်းပြန် အစီအစဉ်အတိုင်း စီပေးသည့် sort -r လည်း ရှိပါသည်။
ကောင်းပြီ၊ ယင်းသည် အလွန် ကောင်းမွန်လှသည်၊ သို့သော် ကျွန်ုပ်တို့သည် Username များကိုသာ ရယူလိုပြီး စာကြောင်းတစ်ကြောင်းလျှင် တစ်ခုစီ မဟုတ်ဘဲ ထုတ်ယူချင်ပါသည်-
ssh myserver journalctl
| grep sshd
| grep "Disconnected from"
| sed -E 's/.*Disconnected from (invalid |authenticating )?user (.*) [^ ]+ port [0-9]+( \[preauth\])?$/\2/'
| sort | uniq -c
| sort -nk1,1 | tail -n10
| awk '{print $2}' | paste -sd,
paste ဖြင့် စတင်ကြည့်ကြပါစို့- ၎င်းသည် စာကြောင်းများကို ပေးထားသော စာလုံးတစ်လုံးတည်းဖြစ်သည့် Delimiter (-d) ဖြင့် ပေါင်းစည်းပေးပါသည် (-s)။ သို့သော် ဤ awk ဆိုသည်မှာ မည်သည့်အရာ နည်း။
awk – another editor
awk သည် စာသား Stream များကို ပြုပြင်ဆောင်ရွက်ရာတွင် လွန်စွာ ကျွမ်းကျင်သည့် Programming ဓာတ်ခံရှိသော ဘာသာစကားတစ်ခု ဖြစ်ပါသည်။ အကယ်၍ awk ကို သေချာစွာ သင်ယူမည်ဆိုပါက ပြောစရာများ စွာ ရှိသော်လည်း ဤနေရာတွင် အခြား အရာများကဲ့သို့ပင် အခြေခံများကိုသာ သွားရောက်မည် ဖြစ်ပါသည်။
ပထမဦးစွာ {print $2} က မည်သည်ကို ပြုလုပ်သနည်း။ အမှန်တော့ awk ပရိုဂရမ်များသည် ရွေးချယ်နိုင်သော (optional) Pattern တစ်ခု အပြင် ပေးထားသော စာကြောင်းနှင့် ကိုက်ညီပါက မည်သို့ ပြုလုပ်ရမည်ကို ဖော်ပြသည့် Block တစ်ခု ပုံစံ ယူကြသည်။ ပုံသေ Pattern (ကျွန်ုပ်တို့ အထက်တွင် အသုံးပြုခဲ့သည့်အတိုင်း) သည် စာကြောင်း အားလုံးနှင့် ကိုက်ညီပါသည်။ Block အတွင်းတွင် $0 ကို စာကြောင်း တစ်ကြောင်းလုံး၏ အကြောင်းအရာအဖြစ် သတ်မှတ်ပြီး $1 မှ $n အထိကို awk field separator (ပုံမှန်အားဖြင့် whitespace၊ -F ဖြင့် ပြောင်းလဲနိုင်သည်) ဖြင့် ခွဲခြားထားသော စာကြောင်း၏ n ခုမြောက် field အဖြစ် သတ်မှတ်ပါသည်။ ဤနေရာတွင် စာကြောင်းတိုင်းအတွက် ဒုတိယမြောက် Field ၏ အကြောင်းအရာကို ရိုက်နှိပ်ရန် ပြောထားခြင်းဖြစ်ပြီး ယင်းမှာ Username ဖြစ်နေပါသည်!
ပိုမို ဆန်းသစ်သော အရာတစ်ခုခုကို ပြုလုပ်နိုင် မနိုင် ကြည့်ကြပါစို့။ c ဖြင့် စပြီး e ဖြင့် ဆုံးသည့် တစ်ကြိမ်သာ သုံးထားသော Username အရေအတွက်ကို တွက်ချက်ကြပါစို့-
| awk '$1 == 1 && $2 ~ /^c[^ ]*e$/ { print $2 }' | wc -l
ဤနေရာတွင် ရှင်းလင်းစရာများစွာ ရှိပါသည်။ ပထမဦးစွာ ကျွန်ုပ်တို့ထံတွင် Pattern တစ်ခု ရှိလာသည်ကို သတိပြုပါ ({...} မတိုင်မီ ပါဝင်သော အရာများ)။ ယင်း Pattern က စာကြောင်း၏ ပထမ Field သည် 1 နှင့် ညီမျှရမည်ဖြစ်ကြောင်း (uniq -c မှ ပေးသော အရေအတွက် ဖြစ်သည်)၊ ထို့အပြင် ဒုတိယ Field သည် ပေးထားသော Regular Expression နှင့် ကိုက်ညီရမည် ဖြစ်ကြောင်း ဖော်ပြထားသည်။ Block ကမူ Username ကို ထုတ်ပြရန်သာ ပြောထားပါသည်။ ထို့နောက် Output စာကြောင်း အရေအတွက်ကို wc -l ဖြင့် ရေတွက်လိုက်ပါသည်။
သို့သော် awk သည် Programming ဘာသာစကားတစ်ခု ဖြစ်သည်ကို မှတ်မိပါသလား။
BEGIN { rows = 0 }
$1 == 1 && $2 ~ /^c[^ ]*e$/ { rows += $1 }
END { print rows }
BEGIN သည် Input ၏ အစနှင့် ကိုက်ညီသော Pattern ဖြစ်သည် (ထို့အပြင် END သည် အဆုံးနှင့် ကိုက်ညီသည်)။ ယခု စာကြောင်းအလိုက် Block သည် ပထမ Field မှ အရေအတွက်ကို ပေါင်းစပ်သွားရုံသာ ဖြစ်ပြီး (ဤနေရာတွင် အမြဲ 1 ဖြစ်နေမည် ဖြစ်သော်လည်း) ထို့နောက် အဆုံးတွင် ထုတ်ပြပေးမည် ဖြစ်ပါသည်။ အမှန်တော့ awk က အရာအားလုံးကို ပြုလုပ်နိုင်သောကြောင့် grep နှင့် sed တို့ကို လုံးဝ ဖယ်ရှားပစ်နိုင်သော်လည်း ယင်းကို ဖတ်ရှုသူများအတွက် လေ့ကျင့်ခန်းအဖြစ် ချန်လှပ်ထားခဲ့ပါမည်။
Analyzing data
သင်သည် သင်္ချာ တွက်ချက်မှုများကို ပြုလုပ်နိုင်ပါသည်!
| paste -sd+ | bc -l
echo "2*($(data | paste -sd+))" | bc -l
သင်သည် စာရင်းအင်း (stats) များကို နည်းလမ်းအမျိုးမျိုးဖြင့် ရယူနိုင်ပါသည်။ st သည် သပ်ရပ်ကောင်းမွန်လှသော်လည်း အကယ်၍ သင့်ထံတွင် R ရှိပြီးသားဆိုပါက-
ssh myserver journalctl
| grep sshd
| grep "Disconnected from"
| sed -E 's/.*Disconnected from (invalid |authenticating )?user (.*) [^ ]+ port [0-9]+( \[preauth\])?$/\2/'
| sort | uniq -c
| awk '{print $1}' | R --slave -e 'x <- scan(file="stdin", quiet=TRUE); summary(x)'
R သည် ဒေတာ သုံးသပ်လေ့လာခြင်းနှင့် Plot တိုင်းတာပုံဆွဲခြင်း တို့တွင် ကျွမ်းကျင်သော အခြား (ဆန်းကြယ်သည့်) Programming ဘာသာစကားတစ်ခု ဖြစ်ပါသည်။ ကျွန်ုပ်တို့ အသေးစိတ်များစွာ သွားရောက်မည် မဟုတ်သော်လည်း summary သည် Matrix တစ်ခုအကြောင်း စာရင်းအင်း အကျဉ်းချုပ်ကို ထုတ်ပြပေးကြောင်း ဖော်ပြပါက လုံလောက်ပါသည်၊ ထို့အပြင် ဂဏန်းများ ပါဝင်သော Input Stream မှ Matrix တစ်ခုကို တွက်ချက်လိုက်သောကြောင့် R သည် ကျွန်ုပ်တို့ လိုချင်သော စာရင်းအင်းများကို ထုတ်ပေးလိုက်ခြင်း ဖြစ်ပါသည်!
အကယ်၍ ရိုးရှင်းသော Plotting အချို့ကိုသာ ပြုလုပ်လိုပါက gnuplot ကို အသုံးပြုနိုင်ပါသည်-
ssh myserver journalctl
| grep sshd
| grep "Disconnected from"
| sed -E 's/.*Disconnected from (invalid |authenticating )?user (.*) [^ ]+ port [0-9]+( \[preauth\])?$/\2/'
| sort | uniq -c
| sort -nk1,1 | tail -n10
| gnuplot -p -e 'set boxwidth 0.5; plot "-" using 1:xtic(2) with boxes'
Data wrangling to make arguments
အချို့ အချိန်များတွင် ပိုမို ရှည်လျားသော စာရင်းအပေါ် အခြေခံ၍ ထည့်သွင်းရန် သို့မဟုတ် ဖယ်ရှားရန် အရာများကို ရှာဖွေနိုင်ရန် Data Wrangling ပြုလုပ်လိုကြသည်။ ယခုတိုင်အောင် ဆွေးနွေးခဲ့သော Data Wrangling နည်းလမ်းများ + xargs သည် စွမ်းအားထက်မြက်သည့် အတွဲအစပ်တစ်ခု ဖြစ်နိုင်ပါသည်-
rustup toolchain list | grep nightly | grep -vE "nightly-x86|01-17" | sed 's/-x86.*//' | xargs rustup toolchain uninstall
လေ့ကျင့်ခန်းများ
- အကယ်၍ သင်သည် Regular Expression များနှင့် ယဉ်ပါးမှု မရှိသေးပါက ဤနေရာ တွင် အခြေခံ အများစုကို လွှမ်းခြုံထားသော တိုတောင်းသည့် တိုက်ရိုက် လေ့ကျင့်နိုင်သော Tutorial ရှိပါသည်။
sed s/REGEX/SUBSTITUTION/gသည် ပုံမှန် sed နှင့် မည်သို့ ကွဲပြားသနည်း။/Iသို့မဟုတ်/mတို့ကော မည်သို့ ကွဲပြားသနည်း။- In-place အစားထိုးမှု ပြုလုပ်ရန်အတွက်
sed s/REGEX/SUBSTITUTION/ input.txt > input.txtကဲ့သို့ ပြုလုပ်ရန် လွန်စွာ ဆွဲဆောင်မှု ရှိသည်။ သို့သော် ဤသည်မှာ မကောင်းသော အကြံဉာဏ် ဖြစ်သည်၊ အဘယ်ကြောင့်နည်း။ ဤသည်မှာsedတစ်ခုတည်းအတွက် ဖြစ်ပေါ်သော အရာ ဟုတ်ပါသလား။ - သင် ယဉ်ပါးသည့် ဘာသာစကားတစ်ခုခုတွင် Regex ကို အသုံးပြု၍ ရိုးရှင်းသော grep နှင့် တူညီသော Tool တစ်ခု အကောင်အထည်ဖော်ပါ။ အကယ်၍ Output ကို grep ကဲ့သို့ အရောင်များဖြင့် ပေါ်လွင်စေလိုပါက ANSI color escape sequence များကို ရှာဖွေပါ။
- အချို့သော အချိန်များတွင် ဖိုင်အမည်များ ပြောင်းလဲခြင်းကဲ့သို့သော လုပ်ဆောင်ချက်များသည်
mvကဲ့သို့သော ရိုးရှင်းသည့် Command များဖြင့် ပြုလုပ်ရန် ရှုပ်ထွေးနိုင်ပါသည်။renameသည် ယင်းကို ပြုလုပ်ရန် အသုံးဝင်သော Tool တစ်ခုဖြစ်ပြီး sed ကဲ့သို့ Syntax ရှိပါသည်။ အမည်တွင် Space ပါသော ဖိုင်များစွာ ဖန်တီးကြည့်ပြီး ယင်းတို့ကို Underscore ဖြင့် အစားထိုးရန်renameကို အသုံးပြုပါ။ - သင်၏ ပြီးခဲ့သော Reboot သုံးကြိမ်အကြား မျှဝေထားခြင်း မရှိသော Boot မက်ဆေ့ဂျ်များကို ရှာဖွေပါ (
journalctl၏-bflag ကို ကြည့်ပါ)။ ယင်းက ပိုမို လွယ်ကူစေနိုင်သည့်အတွက် Boot Log အားလုံးကို ဖိုင်တစ်ခုတည်းအဖြစ် ပေါင်းစပ်လိုက်နိုင်ပါသည်။ - အောက်ပါ မက်ဆေ့ဂျ်များ၏ Log Timestamp ကို အသုံးပြု၍ ပြီးခဲ့သော Reboot ၁၀ ကြိမ်အတွင်း သင်၏ စနစ် Boot တက်ချိန် စာရင်းအင်းများကို ထုတ်ယူပါ-
Logs begin at ...နှင့်
systemd[577]: Startup finished in ... /usr/share/dict/wordsတွင် နည်းဆုံးaသုံးခု ပါဝင်ပြီး အဆုံးတွင်'sပါဝင်ခြင်း မရှိသော စကားလုံး အရေအတွက်ကို ရှာပါ။ ယင်း စကားလုံးများ၏ အသုံးအများဆုံး အဆုံးသတ် စာလုံးနှစ်လုံး ပုံစံ သုံးခုမှာ မည်သည်တို့ နည်း။sed၏ycommand သို့မဟုတ်trပရိုဂရမ်သည် စာလုံးကြီး/စာလုံးသေး မခွဲခြားဘဲ စစ်ဆေးရာတွင် ကူညီပေးနိုင်ပါသည်။ ယင်း စကားလုံးနှစ်လုံး ပုံစံ အရေအတွက် မည်မျှ ရှိသနည်း။ ထို့အပြင် ပိုမို စိန်ခေါ်မှုအတွက်- မည်သည့် ပုံစံများ ပါဝင်ခြင်း မရှိပါသနည်း။- ဤအရာ သို့မဟုတ် ဤအရာ ကဲ့သို့သော အွန်လိုင်း ဒေတာ အစုအဝေး တစ်ခုကို ရှာပါ။ သို့မဟုတ် ဤနေရာမှ အခြား ဒေတာ အစုအဝေး တစ်ခုလည်း ဖြစ်နိုင်ပါသည်။
curlကို အသုံးပြု၍ ယင်းကို ရယူပြီး ဂဏန်း ဒေတာ Column နှစ်ခုကိုသာ ထုတ်ယူပါ။ အကယ်၍ HTML ဒေတာကို ရယူနေခြင်းဖြစ်ပါကpupသည် ကူညီပေးနိုင်ပါသည်။ JSON ဒေတာအတွက်မူjqကို စမ်းသပ်ကြည့်ပါ။ Command တစ်ခုတည်းဖြင့် Column တစ်ခု၏ အနည်းဆုံးနှင့် အများဆုံး ကိန်းဂဏန်းကို ရှာပါ၊ အခြား Command တစ်ခုဖြင့် Column နှစ်ခုအကြား ခြားနားချက်၏ စုစုပေါင်း ပေါင်းလဒ်ကို ရှာပါ။
Licensed under CC BY-NC-SA.