Computer >> Máy Tính >  >> Lập trình >> Lập trình BASH

Giữ bạn trong vòng lặp - Ví dụ về Bash For, While, Until Loop

Giữ bạn trong vòng lặp - Ví dụ về Bash For, While, Until Loop Các câu lệnh lặp được sử dụng để buộc một chương trình thực hiện lặp lại một câu lệnh. Câu lệnh được thực thi được gọi là phần thân của vòng lặp.

Các vòng lặp thực thi cho đến khi giá trị của biểu thức điều khiển bằng 0. Biểu thức điều khiển có thể là bất kỳ kiểu dữ liệu vô hướng nào.

Ngôn ngữ shell cũng cung cấp một số câu lệnh lặp hoặc lặp. Trong bài viết này, chúng ta hãy xem xét các câu lệnh lặp mà bash cung cấp bằng cách sử dụng một số ví dụ.

Bash hỗ trợ ba loại câu lệnh lặp sau đây

  1. Vòng lặp for
  2. Vòng lặp While
  3. Vòng lặp Until

Bài viết này là một phần của loạt bài Hướng dẫn về Bash đang thực hiện.

Các vòng lặp có thể được lồng vào nhau. Giống như bất kỳ ngôn ngữ lập trình nào khác, bash cũng hỗ trợ câu lệnh break để thoát khỏi vòng lặp hiện tại và câu lệnh continue để tiếp tục lặp lại câu lệnh lặp tiếp theo.

Bash For Loop - Phương pháp đầu tiên

Vòng lặp for thường được sử dụng khi biết số lần lặp trước khi vào vòng lặp bash. Bash hỗ trợ hai loại vòng lặp for. Dạng đầu tiên của vòng lặp bash for là:

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

Trong cú pháp trên:

  • cho, trong, làm và hoàn thành là các từ khóa
  • Danh sách là bất kỳ danh sách nào có danh sách các mục
  • varname là bất kỳ tên biến Bash nào.

Trong biểu mẫu này, câu lệnh for thực hiện lệnh nằm trong một phần nội dung, một lần cho mỗi mục trong danh sách. Mục hiện tại từ danh sách sẽ được lưu trữ trong một biến “varname” mỗi lần qua vòng lặp. Varname này có thể được xử lý trong phần thân của vòng lặp. Danh sách này có thể là một biến chứa một số từ được phân tách bằng dấu cách. Nếu thiếu danh sách trong câu lệnh for, thì nó sẽ nhận tham số vị trí đã được truyền vào shell.

Bash For Loop Ví dụ 1. Giải nén tất cả tệp Zip

Ví dụ sau đây tìm danh sách các tệp phù hợp với “* .zip *” trong thư mục gốc và tạo một thư mục mới ở cùng vị trí nơi tệp zip tồn tại và giải nén nội dung tệp zip.

# 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
  • Trong ví dụ này, lệnh find trả về danh sách các tệp, từ đó mỗi tệp sẽ được xử lý thông qua một vòng lặp.
  • Đối với mỗi mục, nó sẽ tạo thư mục với tên của tệp zip và sao chép tệp zip vào thư mục mới được tạo và giải nén tệp zip từ đó.
  • Câu lệnh echo, echo $ {file ## / * /} chỉ cung cấp cho bạn tên tệp chứ không phải đường dẫn.
# ./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

Tương tự như vòng lặp Bash, Awk cũng cung cấp vòng lặp for và vòng lặp while như chúng ta đã thảo luận trong bài viết Awk While và For Loop.

Bash For Loop - Phương pháp thứ hai

Dạng thứ hai của vòng lặp for tương tự như vòng lặp for trong ngôn ngữ lập trình ‘C’, có ba biểu thức (khởi tạo, điều kiện và cập nhật).

for (( expr1; expr2; expr3 ))
         do
		commands
         done
  • Trong cú pháp lệnh bash for ở trên, trước lần lặp đầu tiên, expr1 được đánh giá. Điều này thường được sử dụng để khởi tạo các biến cho vòng lặp.
  • Tất cả các câu lệnh giữa do và done được thực thi lặp đi lặp lại cho đến khi giá trị của expr2 là TRUE.
  • Sau mỗi lần lặp lại của vòng lặp, expr3 được đánh giá. Điều này thường được sử dụng để tăng bộ đếm vòng lặp.

Ví dụ sau tạo ra n số ngẫu nhiên.

Bash Ví dụ 2. Tạo n số ngẫu nhiên

$ 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

Trong đoạn mã trên, vòng lặp for tạo ra số ngẫu nhiên ở số lần tối đa. RANDOM là một hàm bash nội bộ trả về một số nguyên ngẫu nhiên tại mỗi lần gọi.

Bash While Loop

Một câu lệnh lặp khác được cung cấp bởi ngôn ngữ lập trình shell là câu lệnh while.

Syntax:
while expression
do
	commands
done

Trong cú pháp vòng lặp while ở trên:

  • while, do, done là các từ khóa
  • Biểu thức là bất kỳ biểu thức nào trả về giá trị vô hướng
  • Câu lệnh while khiến một khối mã được thực thi trong khi biểu thức điều kiện đã cung cấp là đúng.

Bash While Ví dụ 3. Ghi nội dung vào tệp

Ví dụ sau đây đọc dữ liệu từ stdout và ghi vào một tệp.

$ 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

Ví dụ trên, đọc tên tệp từ người dùng và đọc các dòng dữ liệu từ stdin và nối mỗi dòng với một tên tệp nhất định. Khi EOF vào, quá trình đọc sẽ không thành công, vì vậy vòng lặp kết thúc ở đó.

Nếu bạn đang viết nhiều tập lệnh bash, bạn có thể sử dụng Vim editor làm IDE Bash bằng cách sử dụng plugin Vim bash-support như chúng ta đã thảo luận trước đó.

Bash While Ví dụ 4. Đọc nội dung của tệp

Trong ví dụ trước, nó đọc dữ liệu từ stdout và ghi nó vào một tệp. Trong ví dụ này, nó đọc nội dung tệp
và ghi nó vào một 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

Trong ví dụ này, nó lấy tên tệp để đọc và sử dụng tệp thực thi, nó chuyển hướng stdin đến một tệp. Kể từ thời điểm đó, tất cả stdin đến từ tệp đó, chứ không phải từ bàn phím. lệnh read đọc dòng từ stdin, vì vậy vòng lặp while đọc stdin, cho đến khi EOF xảy ra.

Bash Until Loop

Câu lệnh Until rất giống về cú pháp và chức năng của câu lệnh while. Sự khác biệt thực sự duy nhất giữa cả hai là câu lệnh Until thực thi khối mã của nó trong khi biểu thức điều kiện của nó là sai và câu lệnh while thực thi khối mã của nó trong khi biểu thức điều kiện của nó là đúng.

syntax:

until expression
	do
	   commands #body of the loop
	done

Trong cú pháp bash Until ở trên:
where Until, do, done là các từ khóa
biểu thức bất kỳ biểu thức điều kiện nào

Bash Until Ví dụ 5. Theo dõi tệp nhật ký

Ví dụ này giám sát kích thước của logfile, khi kích thước logfile đạt 2000byte, nó sẽ lấy bản sao của 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

Câu lệnh Until tiếp tục thực hiện phần thân của vòng lặp, cho đến khi điều kiện trở thành true. Trong điều kiện ví dụ này là kích thước của tệp lớn hơn 2000 byte, vì vậy nó sẽ sao chép tệp khi nó đạt đến 2000 byte.

Ngoài ra, hãy nhớ tham khảo các ví dụ về Mảng Bash trước đây của chúng tôi.

Bash Until Ví dụ 6. Chờ Máy khởi động

Ví dụ này được sử dụng để đợi cho đến khi máy xuất hiện trước khi thực hiện một ssh cho máy đó. Câu lệnh lặp cho đến khi kết thúc chỉ khi ping đưa ra phản hồi.

$ 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

Vòng lặp Until khá hữu ích ở dòng lệnh, như một cách để đợi các sự kiện nhất định xảy ra.