shell与其他语言一样也支持for、while循环

for循环的一般格式如下:


 1 #!/bin/sh
2
3 for 变量 in 列表
4 do
5 command 1
6 command 2
7 command 1
8 .........
9 command n
10 done


列表是一组值(数字、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。

列表也可以是一个文件:

in 列表是可选的,如果不用它,for 循环使用命令行的位置参数。


1 #!/bin/sh
2
3 for line in 1 2 3 4 5 6 7
4 do
5 echo "line is $line"
6 done


结果:

[root@localhost 1st]# sh test.sh

line is 1

line is 2

line is 3

line is 4

line is 5

line is 6

line is 7

下面用for循环读一个文件:

查看文件内容


1 [root@localhost 1st]# cat test.txt 
2 hello
3 wolrd
4 hello
5 shell
6 [root@localhost 1st]#


code:


1 #!/bin/sh
2
3 FILE=./test.txt
4
5 for line in $(<$FILE)
6 do
7 echo "line is: $line"
8 done


Results:


1 [root@localhost 1st]# sh xx.sh  
2 line is: hello
3 line is: wolrd
4 line is: hello
5 line is: shell
6 [root@localhost 1st]#


while循环的一般格式如下:


1 while command
2 do
3
4 statement
5
6 done


code:


 1 #!/bin/sh
2
3 i=0
4 sum=0
5 while [ $i -le 100 ]
6 do
7 sum=$(($sum + $i))
8 i=$(($i + 1))
9 done
10 echo "sum is $sum"


rusults:


1 [root@localhost 1st]# sh xx.sh 
2 sum is 5050
3 [root@localhost 1st]#


if语句的一般格式如下:


1 if ....; then
2 ....
3 elif ....; then
4 ....
5 else
6 ....
7 fi


if 条件语句:

文件表达式:


 1 [ -f "somefile" ] :  判断是否是一个文件 
2 [ -x "/bin/ls" ] :   判断/bin/ls是否存在并有可执行权限
3 [ -n "$var" ] :    判断$var变量是否有值
4 [ "$a" = "$b" ] :  判断$a和$b是否相等
5 -r file       用户可读为真
6  -w file       用户可写为真
7  -x file       用户可执行为真
8  -f file       文件为正规文件为真
9  -d file       文件为目录为真
10  -c file       文件为字符特殊文件为真
11  -b file       文件为块特殊文件为真
12  -s file       文件大小非0时为真
13  -t file       当文件描述符(默认为1)指定的设备为终端时为真


字符串表达式:

[string string_operator string]

这里string_operator可为如下几种:


1 =     两个字符串相等。
2 != 两个字符串不等。
3 -z 空串。
4 -n 非空串


eg:


1  #!/bin/sh
2
3 NUMS="hello"
4 [ $NUMS = "hello" ]
5
6 echo $?


results:


1 [root@localhost 1st]# sh xx.sh  
2 0


 整数表达式:


1 -eq   数值相等。
2 -ne 数值不相等。
3 -gt 第一个数大于第二个数。
4 -lt 第一个数小于第二个数。
5 -le 第一个数小于等于第二个数。
6 -ge 第一个数大于等于第二个数。


 Eg:


1 #!/bin/sh
2
3 NUMS=130
4 if [ $NUMS -eq "130" ]; then
5
6 echo "equal"
7 else
8 echo "not equal"
9 fi


results:


1 [root@localhost 1st]# sh xx.sh 
2 equal


下满贴出一个用shell写的简单图书管理系统:


  1 #!/bin/bash
2 #Name:Books Management System(BMS)
3 #Author:DREAM
4 file=books.txt
5 function information
6 {
7 echo "Books Management System(BMS)"
8 echo "---------------------------"
9 echo -e " 1: ADD Books"
10 echo -e " 2: Show Books"
11 echo -e " 3: Select Books"
12 echo -e " 4: Delete Books"
13 echo -e " 5: Exit System"
14 #echo
15 echo "---------------------------"
16 read -p "please input your choice:" num
17 echo
18
19 case "$num" in
20 1) Add
21 ;;
22 2) Show
23 ;;
24 3) Select
25 ;;
26 4) Delete
27 ;;
28 5) exit
29 ;;
30 *) information
31 ;;
32 esac
33 }
34
35 function Add
36 {
37 echo -e "please books information eg:(English 101 Jerry)"
38 echo
39 read -p "please input books name: " books_name
40 read -p "please input books number: " books_num
41 read -p "please input books author: " books_author
42
43 echo -e "$books_name\t$books_num\t$books_author" >>$file && {
44 echo "Add Books success"
45 echo "---------------------------"
46 }
47 if [ $? -ne 0 ]
48 then
49 echo "Add Books failure"
50 fi
51
52 information
53 }
54
55 function Show
56 {
57 echo -e "Bname\tBnum\tBauthor"
58 grep -Ev "^$" $file
59 echo "-----------------------"
60 echo
61 information
62 }
63
64 function Search_menu
65 {
66 echo "-----------------------"
67 echo -e " 1: Search By Bname"
68 echo -e " 2: Search By Bnum"
69 echo -e " 3: Search By Bauthor"
70 echo -e " 4: Eixt Search System"
71 echo
72 echo "-----------------------"
73 }
74
75 function Select
76 {
77 Search_menu
78 read -p "please input your choice:" ch
79 case "$ch" in
80 1)
81 read -p "please input books name: " name
82 echo -e "Bname\tBnum\tBauthor\n-------------------------"
83 awk '{if($1~/^'$name'/) print $0}' $file
84 echo "-------------------------"
85 if [ $? -ne 0 ]
86 then
87 echo "the file no exist"
88 fi
89 ;;
90 2)
91 read -p "please input books number: " num
92 echo -e "Bname\tBnum\tBauthor\n-------------------------"
93 awk -v s=$num '$2==s {print $0}' $file 2>/dev/null
94 echo "-------------------------"
95 if [ $? -ne 0 ]
96 then
97 echo "the file no exist"
98 fi
99 echo $?
100 ;;
101 3)
102 read -p "please input books author: " author
103 echo -e "Bname\tBnum\tBauthor\n-------------------------"
104 awk '{if($3~/'$author'/) print $0}' $file
105 echo "-------------------------"
106 if [ $? -ne 0 ]
107 then
108 echo "the file no exist"
109 fi
110 echo $?
111
112 ;;
113 4) exit
114 ;;
115 *) Select
116 ;;
117 esac
118 echo
119 information
120 }
121
122 function Delete
123 {
124 read -p "please input your want delete boos number:" num
125 sed -i "/$num/d" $file
126
127 if [ $? -ne 0 ]
128 then
129 echo "success failure"
130 fi
131
132 information
133 }
134
135 information


 利用popen快速获取一个shell命令的返回值

优点:避免了生成临时文件

函数原型:


1  #include <stdio.h>
2
3 FILE *popen(const char *command, const char *type);
4
5 int pclose(FILE *stream);


函数说明:

  popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程。这个管道必须由pclose()函数关闭,而不是fclose()函数。pclose()函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。如果shell不能被执行,则pclose()返回的终止状态与shell已执行exit一样。

  type参数只能是读("r")或者写("w")中的一种,得到的返回值(标准I/O流)也具有和type相应的只读或只写类型。如果type是"r"则文件指针连接到command的标准输出;如果type是"w"则文件指针连接到command的标准输入。

  command参数是一个指向以NULL结束的shell命令字符串的指针。这行命令将被传到bin/sh并使用-c标志,shell将执行这个命令。

  popen()的返回值是个标准I/O流,必须由pclose来终止。前面提到这个流是单向的(只能用于读或写)。向这个流写内容相当于写入该命令的标准输入,命令的标准输出和调用popen()的进程相同;与之相反的,从流中读数据相当于读取命令的标准输出,命令的标准输入和调用popen()的进程相同。

返回值:

  如果调用fork()或pipe()失败,或者不能分配内存将返回NULL,否则返回标准I/O流。popen()没有为内存分配失败设置errno值。如果调用fork()或pipe()时出现错误,errno被设为相应的错误类型。如果type参数不合法,errno将返回EINVAL。

下面是使用popen获取主机中虚拟机个数的范例:


 1 #include <stdio.h>
2 #include <string.h>
3
4 int main()
5 {
6 FILE *fp;
7 size_t value = 0;
8 int nums;
9 char cmd[1024] = {0};
10 int guestnums;
11
12 strcpy(cmd, "virsh list --all | sed -n '3, $p' | grep -v '^$' | wc -l");
13
14 /*使用popen获取shell命令返回值*/
15 if((fp = popen(cmd, "r")) != NULL) {
16
17 if(fgets((char *)&nums, 2, fp))
18 {
19 guestnums = atoi((char *)&nums);
20 }
21 }
22
23 printf("%d\n", guestnums);
24 pclose(fp);
25
26 return 0;
27
28 }