Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม Bash

เชี่ยวชาญ Bash Loops: For, While, Until Examples อธิบายครบถ้วน

Looping Statements ใช้บังคับให้ Program Execute Statement ซ้ำๆ Executed Statement เรียกว่า Loop Body

Loops Execute จนกว่า Controlling Expression จะเป็น 0 Controlling Expression อาจเป็น Scalar Data Type ใดๆ

Shell Language ก็มี Iteration/Looping Statements หลายแบบ ในบทความนี้ มาทบทวน Looping Statements ที่ Bash ให้มา พร้อมตัวอย่าง

Bash รองรับ Looping Statements 3 ประเภท:

  1. For Loop
  2. While Loop
  3. Until Loop

บทความนี้เป็นส่วนหนึ่งของชุด Bash Tutorial Series ต่อเนื่อง

Loops สามารถ Nested ได้ เหมือนภาษาโปรแกรมอื่น Bash ก็มี Break Statement ออกจาก Loop ปัจจุบัน และ Continue Statement Resume Iteration ถัดไปของ Loop Statement

Bash For Loop – วิธีแรก

For Loops ใช้เมื่อจำนวน Iterations รู้จักก่อนเข้ Loop Bash รองรับ For Loop 2 แบบ รูปแบบแรกของ Bash For Loop:

for varname in list
do
  commands  ## Body of the loop
done

ใน Syntax ข้างต้น:

  • for, in, do และ done เป็น Keywords
  • List คือ List ใดๆ ที่มี List of Items
  • varname คือ Bash Variable Name ใดๆ

ในรูปแบบนี้ For Statement Execute Commands ใน Body หนึ่งครั้งต่อ Item ใน List Item ปัจจุบันจาก List จะเก็บใน Variable "varname" ทุกครั้งผ่าน Loop varname นี้สามารถ Process ใน Body ของ Loopได้ List นี้อาจเป็น Variable ที่มีหลาย Words คั่นด้วย Spaces ถ้า List หายไปใน For Statement จะใช้ Positional Parameters ที่ส่งเข้า Shell

Bash For Loop Example 1. Unzip ไฟล์ Zip ทั้งหมด

ตัวอย่างต่อไปนี้หา List of Files ที่ Match "*.zip*" ใน Root Directory สร้าง Directory ใหม่ที่ Location เดียวกับ Zip File และ Unzip เนื้อหา

# cat zip_unzip.sh
#! /bin/bash
# Find files which has .zip
for file in `find /root -name "*.zip*" -type f`
do
  # Skip the extension .zip
  dirname=`echo ${file} | awk -F'.' '{print $1}'`
  # Create the directory
  mkdir $dirname
  # Copy the zip file
  cp ${file} ${dirname}
  cd $dirname
  # Unzip the zip file from newly created directory
  unzip ${dirname}/$(echo ${file##/*/})
done
  • ในตัวอย่าง Find Command คืนค่า List of Files แต่ละ File จะ Process ผ่าน Loop
  • ต่อ Item สร้าง Directory ชื่อ Zip File Copy Zip File ไป Directory ใหม่ และ Unzip จากที่นั่น
  • Echo Statement echo ${file##/*/} ให้แค่ File Name ไม่ใช่ Path
# ./zip_unzip.sh
Archive: /root/test2/test2.zip
extracting: t1/p
extracting: t1/q
extracting: t1/r
extracting: t1/s
extracting: t1/t
extracting: t1/u
extracting: t1/v
Archive: /root/test1/test1.zip
extracting: t/a
extracting: t/b
extracting: t/c
extracting: t/d
extracting: t/e

คล้าย Bash Loop, Awk ก็มี For Loop และ While Loop ตามที่พูดใน Awk While and For Loop Article

Bash For Loop – วิธีที่สอง

รูปแบบที่สองของ For Loop คล้าย For Loop ใน 'C' Programming Language ซึ่งมี 3 Expressions (Initialization, Condition และ Updation)

for (( expr1; expr2; expr3 ))
do
  commands
done
  • ใน Syntax Bash For Command ข้างต้น ก่อน Iteration แรก expr1 จะ Evaluated ใช้ Initialize Variables สำหรับ Loop ปกติ
  • Statements ระหว่าง do และ done Execute ซ้ำจนกว่า expr2 จะเป็น TRUE
  • หลัง Iteration แต่ละรอบ expr3 จะ Evaluated ใช้ Increment Loop Counter ปกติ

ตัวอย่างต่อไปนี้ Generate N Random Numbers

Bash For Example 2. Generate N Random Numbers

$ cat random.sh
#! /bin/bash
echo -e "How many random numbers you want to generate"
read max
for (( start = 1; start <= $max; start++ ))
do
  echo -e $RANDOM
done
$ ./random.sh
How many random numbers you want to generate
5
6119
27200
1998
12097
9181

ใน Code Snippet ข้างต้น For Loop Generate Random Number Max ครั้ง RANDOM เป็น Internal Bash Function คืนค่า Random Integer ทุกครั้งที่ Invoke

Bash While Loop

Iteration Statement อีกแบบจาก Shell Programming Language คือ While Statement

Syntax: while expression
do
  commands
done

ใน While Loop Syntax ข้างต้น:

  • while, do, done เป็น Keywords
  • Expression คือ Expression ใดๆ ที่คืนค่า Scalar Value
  • While Statement ทำให้ Block of Code Execute ขณะที่ Conditional Expression เป็น True

Bash While Example 3. เขียนเนื้อหาลง File

ตัวอย่างต่อไปนี้อ่าน Data จาก Stdout และเขียนลง File

$ cat writefile.sh
#! /bin/bash
echo -e "Enter absolute path of the file name you want to create"
read file
while read line
do
  echo $line >> $file
done
$ sh writefile.sh
Enter absolute path of the file name you want to create
/tmp/a
while
for
until
$ cat /tmp/a
while
for
until

ตัวอย่างข้างต้นอ่าน Filename จาก User และอ่านบรรทัดจาก Stdin Append แต่ละบรรทัดไป Filename ที่กำหนด เมื่อ EOF Enter Read จะ Fail ดังนั้น Loop จบที่นั่น

ถ้าเขียน Bash Scripts เยอะ สามารถใช้ Vim Editor เป็น Bash IDE ด้วย Vim bash-support Plugin ตามที่พูดไปก่อนหน้า

Bash While Example 4. อ่านเนื้อหา File

ในตัวอย่างก่อนหน้า อ่าน Data จาก Stdout เขียนลง File ตัวอย่างนี้อ่าน File Content และเขียนลง Stdout

$ cat read.sh
#! /bin/bash
echo -e "Enter absolute path of the file name you want to read"
read file
exec <$file  # Redirects stdin to a file
while read line
do
  echo $line
done
$ ./read.sh
Enter absolute path of the file name you want to read
/tmp/a
while
for
until

ในตัวอย่างนี้ ได้ Filename มาอ่าน และด้วย Exec Redirect Stdin ไป File ตั้งแต่จุดนั้น Stdin ทั้งหมดมาจาก File แทน Keyboard Read Command อ่านบรรทัดจาก Stdin ดังนั้น While Loop อ่าน Stdin จนกว่า EOF

Bash Until Loop

Until Statement คล้าย While Statement มากทั้ง Syntax และ Function ความต่างจริงคือ Until Execute Code Block ขณะที่ Conditional Expression เป็น False ในขณะที่ While Execute ขณะที่เป็น True

syntax: until expression
do
  commands  # body of the loop
done

ใน Bash Until Syntax ข้างต้น: where until, do, done เป็น Keywords Expression ใดๆ ที่เป็น Conditional Expression

Bash Until Example 5. Monitor Logfile

ตัวอย่างนี้ Monitor ขนาด Logfile เมื่อ Logfile Size ถึง 2000 Bytes จะ Copy Logfile นั้น

$ cat monitor.sh
file=/tmp/logfile
until [ $(ls -l $file | awk '{print $5}') -gt 2000 ]
do
  echo "Sleeping for next 5 seconds"
  sleep 5
done
date=`date +%s`
cp $file "$file-"$date.bak
$ ./monitor.sh
Sleeping for next 5 seconds
Sleeping for next 5 seconds
$ ls -l /tmp/logfile*
-rw-r--r-- 1 sss sss 2010 Jun 24 12:29 logfile
-rw-r--r-- 1 sss sss 2005 Jun 24 16:09 logfile-1277474574.bak

Until Statement Execute Body ของ Loop ต่อจนกว่า Condition จะเป็น True ในตัวอย่าง Condition คือ File Size มากกว่า 2000 Bytes ดังนั้น Copy File เมื่อถึง 2000 Bytes

อ่านเพิ่มเติม Bash Array Examples ก่อนหน้า

Bash Until Example 6. รอ Machine พร้อม

ตัวอย่างนี้ใช้ Wait จน Machine พร้อมก่อน SSH ไปเครื่องนั้น Until Loop Statement จบก็ต่อเมื่อ Ping ตอบสนอง

$ cat mac_wait.sh
#! /bin/bash
read -p "Enter IP Address:" ipadd
echo $ipadd
until ping -c 1 $ipadd
do
  sleep 60; done
ssh $ipadd
$./mac_wait.sh
Enter IP Address:192.143.2.10
PING 192.143.2.10 (192.143.2.10) 56(84) bytes of data.
--- 192.143.2.10 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
PING 192.143.2.10 (192.143.2.10) 56(84) bytes of data.
64 bytes from 192.143.2.10: icmp_seq=1 ttl=64 time=0.059 ms
--- 192.143.2.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.059/0.059/0.059/0.000 ms
The authenticity of host '192.143.2.10 (192.143.2.10)' can't be established.
Are you sure you want to continue connecting (yes/no)? yes

Until Loop มีประโยชน์มากที่ Command Line เป็นวิธีรอ Certain Events เกิดขึ้น