บทความนี้เกี่ยวกับการอ่านไฟล์ใน Bash Scripts ด้วย While Loop การอ่านไฟล์เป็น Operation พื้นฐานในการเขียนโปรแกรม คุณควรคุ้นเคยกับ Methods ต่างๆ และว่าวิธีไหน Efficient ที่สุด ใน Bash งานเดียวทำได้หลายทางแต่มี Optimal Way เสมอที่ควรทำตาม
ก่อนดูการอ่านไฟล์ด้วย While Loop Primer สั้นๆ เกี่ยว While Loop While Loop Evaluate Condition และ Iterate Code Set เมื่อ Condition เป็น True
while [ CONDITION ] do code block done
มาแยก While Loop Syntax:
- While Loop เริ่มด้วย While Keyword ตามด้วย Condition
- Condition ควรอยู่ใน [ ] หรือ [[ ]] Condition ควร Return True เสมอเพื่อให้ Loop Execute
- Code Block จริงวางระหว่าง Do และ Done
NUMBER=0
while [[ $NUMBER -le 10 ]]
do
echo " Welcome ${NUMBER} times "
(( NUMBER++ ))
done
ตัวอย่างง่าย Loop Execute จน NUMBER ไม่ Greater Than 10 พิมพ์ Echo Statement
พร้อม While เราจะใช้คำสั่ง Read อ่านเนื้อหาไฟล์ทีละบรรทัด Syntax ของ While และ Read รวมกัน ด้านล่าง มีวิธีส่งไฟล์เป็น Input หลายแบบ จะดูทุกแบบ
# SYNTAX while read VARIABLE do code done
Piping ใน Linux
ปกติใช้ Cat Command ดูเนื้อหาไฟล์จาก Terminal และ Pipe Output ของ Cat Command ไป Commands อื่นๆ เช่น Grep, Sort ฯลฯ
เช่นกัน เราใช้ Cat Command อ่านเนื้อหาไฟล์และ Pipe ไป While Loop สำหรับ Demo ใช้ไฟล์ /etc/passwd แต่ไม่ควรแก้ไขไฟล์นี้ Backup ไว้ก่อนหากอยากทดลอง
cat /etc/passwd | while read LREAD
do
echo ${LREAD}
done
มาแยกว่าจะเกิดอะไรขึ้น:
- cat /etc/passwd อ่านเนื้อหาไฟล์ส่งเป็น Input ผ่าน Pipe
- Read Command อ่านแต่ละบรรทัดจาก Cat Command เก็บใน Variable LREAD
- Read Command อ่านจนกว่า EOL จะถูก Interpret
ใช้ Commands อื่นๆ เช่น Head, Tail Pipe ไป While Loop ได้
head -n 5 /etc/passwd | while read LREAD
do
echo ${LREAD}
done
Input Redirection ใน Linux
Redirect เนื้อหาไฟล์ไป While Loop ด้วย Input Redirection Operator (<)
while read LREAD
do
echo ${LREAD}
done < /etc/passwd | head -n 5
เก็บชื่อไฟล์ใน Variable ส่งผ่าน Redirection Operator ได้
FILENAME="/etc/passwd"
while read LREAD
do
echo ${LREAD}
done < ${FILENAME}
ส่งชื่อไฟล์เป็น Argument ให้ Script ได้
while read LREAD
do
echo ${LREAD}
done < $1 | head -n 5
Internal Field Separator (IFS)
คุณอาจทำงานกับ File Formats ต่างๆ (CSV, TXT, JSON) และอยาก Split เนื้อหาไฟล์ด้วย Custom Delimiter ใช้ Internal Field Separator (IFS) Split เนื้อหาและเก็บใน Variables
มา Demo ดู ไฟล์ /etc/passwd มี Colon (:) เป็น Delimiter Split แต่ละคำจากบรรทัดเก็บใน Variable แยกกัน
ตัวอย่างด้านล่าง Split /etc/passwd ด้วย Colon เป็น Separator เก็บแต่ละส่วนใน Variables ต่างๆ
while IFS=":" read A B C D E F G
do
echo ${A}
echo ${B}
echo ${C}
echo ${D}
echo ${E}
echo ${F}
echo ${G}
done < /etc/passwd
แสดงแค่ 1 บรรทัดที่ Split ใน Screenshot ข้างบน เนื่องจากขนาด Screenshot
Empty Lines ใน Linux
Empty Lines ไม่ถูก Ignore เมื่อ Loop ผ่านเนื้อหาไฟล์ สำหรับ Demo สร้าง Sample File เนื้อหาด้านล่าง มี 4 บรรทัดและ Empty Lines บ้าง Leading/Trailing Whitespace, Tab Characters ในบรรทัด 2 และ Escape Characters (\n และ \t)
while read LREAD
do
echo ${LREAD}
done < testfile
เห็นผลลัพธ์ Blank Line ไม่ถูก Ignore สังเกต White Spaces ถูก Trimmed โดย Read Command วิธีง่ายข้าม Blank Lines: ใช้ Test Operator ด้วย Flag -z เช็ค String Length เป็นศูนย์ ทำซ้ำตัวอย่างกับ Test Operator
while read LREAD
do
if [[ ! -z $LREAD ]]
then
echo ${LREAD}
fi
done < testfile
จาก Output Empty Lines ถูก Ignored แล้ว
Escape Characters
Escape Characters เหมือน \n, \t, \c จะไม่ Print เมื่ออ่านไฟล์ Demo ด้วย Sample File เดียวที่มี Escape Characters
while read LREAD
do
echo ${LREAD}
done < testfile
เห็นจาก Output Escape Characters สูญเสียความหมาย เหลือแค่ n และ t แทน \n และ \t ใช้ -r ป้องกัน Backslash Interpretation
while read -r LREAD
do
echo ${LREAD}
done < testfile
ขอจบเท่านี้ หากมี Feedback หรือ Tips แจ้งมาได้ Feedback ของคุณช่วยให้เราสร้าง Content ดีกว่า อ่านต่อและสนับสนุนเราต่อไปนะครับ