目录
一、shell 指令
1.1 体验shell指令
1.2 命令格式
1.3 shell中的通配符
1.4 输入输出重定向
1.5 命令置换
1.6 基本系统维护命令
1.7 Linux的进程管理命令
1.8 文件系统相关命令
1.9 Linux网络配置管理
二、shell 编程
2.1 shell 脚本的基础知识
2.2 shell 变量
2.3 shell 程序和语句
2.3.1 说明性语句
2.3.2 功能性语句
2.3.3 结构性语句
(1)条件语句 if…then…fi
(2)多路分支语句
(3)循环语句
2.4 函数的调用
一、shell 指令
shell命令是用户向系统内核发出控制请求,与之交互的文本流。shell是一个命令行解释器,将用户命令解析为操作系统所能理解的指令,实现用户与操作系统的交互。
1.1 体验shell指令
1.立即关机与重启
使用系统中的图形界面
使用shell命令
在命令行键入一下命令,系统立即关机
sudo shutdown -h now
在命令行键入以下命令,系统立即重启启动
sudo shutdown -r now
sudo reboot now
2.定时关机重启
a.一位老师在对学生进行上机测试,时间限定在45分钟内,否则计算机将自动关机。
sudo shutdown -h +45 “That is all,game over.”
b.系统正在安装软件,安装时间大概需要持续40分钟左右,软件安装之后需要重新启动电脑。用户可以不必一直等候在机旁。
使用下面的命令,计算机会在60分钟后自动重启。
sudo shutdown -r +60
1.2 命令格式
shell提示符标识了命令行的开始。用户在提示符后面输入一条命令并按Enter键,完成向系统提交命令。通常shell命令提示符采用以下的格式:
username@hostname:direction$
用户名 主机名 目录名
1)username:用户名,显示当前登录用户的账户名 (执行的命令是 whoami)
2)hostname: 主机名,显示登录的主机名,例如若远程登录后,则显示登录的主机名;(执行的命令是hostname)
3)direction: 目录名,显示当前所处的路径,当在根目录下显示为“/”,当在用户主目录下显示为“~“;(执行的命令是pwd)
4)通常一条命令包含三个要素:命令名称、选项、参数。命令名称是必须的,选项和参数都可能是选项。命令格式如下:
$ Command [-Options] Argument1 Argument2...
指令 选项 参数1 参数2 ...
$:Shell提示符,如果当前用户为超级用户,提示符为“#”,其他用户的提示符均为“$”;
Command:命令名称,Shell命令或程序,严格区分大小写
Options:命令选项,用于改变命令执行动作的类型,由“-”引导,可以同时带有多个选项;
Argument:命令参数,指出命令作用的对象或目标,有的命令允许带多个参数
5)shell命令格式
1)一条命令的三要数之间用空格隔开;
2)若将多个命令在一行书写,用分号(;)将各命令隔开;
3)如果一条命令不能在一行写完,在行尾使用反斜杠(\)表明该条命令结束。
6)不带选项和参数
1)ls命令未带任何参数,列出当前目录中的所有文件,只显示文件名称
2)命令不带选项或参数,通常意为使用默认选项或参数
1.3 shell中的通配符
当需要用命令处理一组文件,例如file.txt、file2.txt、file3.txt....,用户不必意义输入文件名,可以使用shell通配符。shell命令的通配符含义如下:
通配符 含义 实例
* 匹配任意长度的字符串 用file_*.txt,匹配file_wang.txt、file_lee.txt、file3_liu.txt
? 匹配一个长度的字符 用file_?.txt,匹配file_1.txt、file_2.txt、file_3.txt
[...] 匹配其中指定的一个字符 用file_[otr].txt,匹配file_o.txt、file_r.txt和file_t。txt
[-] 匹配指定的一个字符范围 用file_[a-z].txt,匹配file_a.txt、file_b.txt,直到file_z.txt
[^...] 除了其中指定的字符均可匹配 用file_[^otr].txt,除了file_o.txt、file_t.txt、file_r.txt的其它文件
***管道***:当您将 ls /usr/bin
的输出通过管道 |
传递给 wc -w
时,wc -w
会计算 ls
命令输出的每一行中的单词数量。由于 ls
命令默认会为每个文件或目录输出一行,所以这个组合命令实际上统计的是 /usr/bin
目录下的文件和目录总数。
管道可以把一系列命令链接起来,意味着第一个命令的输出将作为第二个命令的输入,通过管道传递给第二个命令,
第二个命令的输出又将作为第三个命令的输入,以此类推。就像通过使用“|”符连成一个管道。
ls /use/bin | wc -w
1.4 输入输出重定向
1.输入/输出重定向是改变shell命令或程序默认的标准输入/输出目标,重新定向到新的目标。
2.linux中默认的标准输入定义为键盘,标准输出定义为终端窗口。
3.用户可以为当前操作改变输入或输出,迫使某个特定命令的输入或输出来源为外部文件。
重定向符 含义 实例
> file 将file文件重定向为输出源,新建模式 ls /usr > Lsoutput.txt,将ls /usr的执行结果,
写到Lsoutput.txt文件中,若有同名文件将被删除
>> file 将file文件重定向为输出源,追加模式 ls /usr >> Lsoutput.txt,将ls /usr的执行结果,
追加到Lsoutput.txt文件已有内容后
< file 将file文件重定向为输入源 wc < file1,将file1中的内容作为输入传给wc命令
2> 或 &> 将由命令产生的错误信息输入到文件中 ls noexistingfile.txt 2> err.log,使用ls命令,
查看一个不存在的文件时,将系统错误提示保存在err.log文件中
示例: cat命令功能为在标准输出上显示文件。下面通过一个实例,可以更好地理解重定向的功能。
1)cat #使用标准输入/出设备
have a good day! #用户使用标准输入设备——键盘,键入字符串,并按Enter键
have a good day! #系统在标准输出——显示器上,显示用户刚刚输入的字符串
2)cat > file1.txt #输出重定向,将输出定向到文件file1.txt
have a good day! #用户使用标准输入设备——键盘,键入字符串,并按Enter键
#用户输入的字符串被保存在file1.txt文件中
3)cat < file1.txt #输入重定向,将cat命令的输入指定为file1.txt文件
have a good day! #系统在标准输出显示器上,显示cat命令从文件中读出的字符串
1.5 命令置换
命令替换是将一个命令的输出作为另一个命令的参数。命令格式如下所示。
1.其中,命令command2的输出将作为命令command1的参数。需要注意,命令置换的单引号为ESC键下方的“`”键
command1 `command2`
2.pwd命令用于显示当前目录的绝对路径。在上面的命令行中,使用命令置换符,将pwd的运行结果作为ls命令的参数。最终,命令执行结果是显示当前目录的文件内容。
linux@ubuntu:~$ ls `pwd`
Desktop Examples historycommandlist mywork
1.6 基本系统维护命令
1.使用man命令可以找到特定的联机帮助页,并提供简短的命令说明。一般语法格式为:
man commandname
2.passwd
a. 出于系统安全考虑,Linux系统中的每一个帐号都必须同时具备用户名和密码。
b. 可以使用passwd命令,为已有账户重新修改用户口令。
c. 需要说明的是,超级用户root可以修改所有其他用户的口令,而普通用户只能修改自己的用户口令,
如果确要修改超级用户或其他用户口令的话,需要具有超级用户的权限。
d. passwd命令的一般语法格式为:
passwd username
单独使用passwd命令,意为修改当前用户自己的口令。下面命令实例用于修改用户自己的口令。
3.su
a. su命令用于临时改变用户身份,具有其他用户的权限。普通用户可以使用su命令临时具有超级用户的权限;
超级用户也可以使用普通用户身份完成一些操作。当需要放弃当前用户身份,可以使用exit命令切换回来。su命令的一般语法格式为:
su [-c | -m - ] username
b.选项“-c”表示执行一个命令后就结束;-m表示仍保留环境变量不变;-表示转换用户身份时,同时使用该用户的环境。
单独使用su命令,默认为要转换为超级用户root。下面命令实例临时获取超级用户root的权限。
4.echo
echo命令用于在标准输出——显示器上显示一段文字,一般起到提示作用。
5.date
a. date命令用于显示和设置系统日期和时间。date命令的一般语法格式为:
date [-d | -s|-u ] datestr
b. 选项-s表示按照datestr日期显示格式设置日期;单独使用date命令,用于显示系统时钟中当前日期。
6.df
df命令用于查看磁盘空间的使用情况。查看磁盘空间是用户应当经常做的事情,
因为谁也不希望看到根或/var分区在不经意间填满,以便及时清理。df命令的一般格式为:
df [-a | -T | -h | -k ] Filesystem
其中,参数Filesystem表示物理文件系统。各选项的含义如表所示。
选项 含义
-a 显示所有物理文件系统的使用情况,包括虚拟文件系统,如/proc、/sys等
-T 显示物理文件系统的文件格式类型
-h 物理文件系统大小按兆字节为单位显示
-k 物理文件系统大小按千字节为单位显示
7.du
列出目录和文件所使用的磁盘块数,每块占512个字节。
常用参数:
-a :仅列出空闲的文件数
-h :列出磁盘的使用情况(KB)
-s :列出总的空闲空间(KB)
例:
#du –h /etc
1.7 Linux的进程管理命令
1.ps命令查看进程
显示进程(process)的动态
语法:
ps [options]
常见的参数:
-A 列出所有的行程
-w 显示加宽可以显示较多的资讯
-au 显示较详细的资讯
-aux 显示所有包含其他使用者的行程
2.top命令
监视进程
通常会全屏显示,而且会随着进程状态的变化不断更新
整个系统的信息也会显示,为查找问题提供了便利
可以显示系统总共有多少CPU和内存资源以及负载平衡等信息。
3.pstree命令
1.将所有行程以树状图显示,树状图将会以pid(如果有指定)或是以init这个基本进程为根,
如果有指定使用者id,则树状图会只显示该使用者所拥有的进程。
2.参数:
-a 显示该进程的完整指令及参数,如果是被记忆体置换出去的进程则会加上括号
-c 如果有重覆的进程名,则分开列出
4.使用kill命令终止进程
使用kill命令终止进程
kill [-signal] PID
signal是信号,PID是进程号
kill 命令向指定的进程发出一个信号signal,在默认的情况下,kill 命令向指定进程发出信号15,
正常情况下,将杀死那些不捕捉或不忽略这个信号的进程
1.8 文件系统相关命令
1.file
命令功能用于判定一个文件的类型。file命令一般语法格式为:
file [ filename ]
2.mkdir
1.mkdir命令用于创建一个目录。mkdir命令一般语法格式为:
mkdir [ -p ] directory_name
2.其中,directory_name为要创建的目录名,并且不能是已有的目录,通常不允许嵌套创建子目录。
3.使用选项“-p”表示可以嵌套创建子目录,即多层目录。
3.rmdir
命令用于删除一个目录。rmdir命令一般语法格式为:
rmdir [ -p ] directory_name
4.链接文件
a.硬链接是利用Linux中为每个文件分配的物理编号——inode建立链接。因此,硬链接不能跨越文件系统。
b.软链接(符号链接)是利用文件的路径名建立链接。
5.ln命令
1.命令可以用于创建文件的链接文件。ln命令一般语法格式为:
ln [ -s ] target link_name
2.其中,选项“-s”表示为创建软链接。在缺省情况下,创建硬链接。参数target为目标文件,link_name为链接文件名。
如果链接文件名已经存在但不是目录,将不做链接。目标文件可以是任何一个文件名,也可以是一个目录。
linux@ubuntu:~$ ln -s /proc/cpuinfo mycpuinfo
linux@ubuntu:~$ ls –l mycpuinfo
lrwxrwxrwx 1 wdl wdl 13 2007-09-22 00:43 mycpuinfo -> /proc/cpuinfo
以上命令为/proc/cpuinfo文件创建了一个软链接文件。使用“ls –l”命令可以查看到新创建的链接文件所指向的目标文件名。
6.文件的归档和压缩
1.简介
归档文件是将一组文件或目录保存在一个文件中。
压缩文件也是将一组文件或目录保存一个文件中,并按照某种存储格式保存在磁盘上,所占磁盘空间比其中所有文件总和要少。
2.常见压缩工具
压缩工具 解压工具 文件扩展名
gzip gunzip .gz
bzip2 bunzip2 .bz2
zip unzip .zip
3.tar命令
tar命令主要用于将若干文件或目录合并为一个文件,以便备份和压缩。当然,之后出现tar程序的改进版本,可以实现在合并归档的同时进行压缩。
tar命令符号模式的一般语法格式为:
tar [ -t | -x | -u | -c | -v | -f | -j | -z ] tarfile filelist
-t 显示归档文件的内容
-x 释放归档文件
-u 更新归档文件
-c 创建一个新的归档文件
-v 显示归档和释放的过程信息
-f 用户指定归档文件的文件名,否则使用默认名称
-j 由tar生成归档,然后由bzip2压缩
-z 由tar生成归档,然后由gzip压缩
第一,将myExamples/目录下的所有文件全部归档,打包到一个文件中myExamples.tar;
第二,将myExamples/目录下的所有文件全部归档,并使用bzip2压缩成一个文件myExamples.tar.bz;
第三,将myExamples/目录下的所有文件全部归档,并使用gzip压缩成一个文件myExamples.tar.gz。
linux@ubuntu:~$ tar –cf myExamples.tar myExamples
linux@ubuntu:~$ tar -cjf myExamples.tar.bz myExamples
linux@ubuntu:~$ tar -czf myExamples.tar.gz myExamples
linux@ubuntu:~$ ls -lh myExamples.tar*
-rw-r--r-- 1 wdl wdl 9.3M 2007-09-23 00:42 myExamples.tar
-rw-r--r-- 1 wdl wdl 8.6M 2007-09-23 00:43 myExamples.tar.bz
-rw-r--r-- 1 wdl wdl 8.5M 2007-09-23 00:44 myExamples.tar.gz
如果想查看一下归档文件中的详细内容,使用类似以下命令:
linux@ubuntu~$ tar –tvf myExamples.tar.gz
使用以下命令完成tar文件的释放。其中,“tar -xjf”和“tar –xzf”等效与先解压缩后释放tar文件。
linux@ubuntu:~$ tar –xvf myExamples.tar
linux@ubuntu:~$ tar -xvjf myExamples.tar.bz
linux@ubuntu:~$ tar
1.9 Linux网络配置管理
1.网络配置基础
实现Linux网络配置的惟一目标就是修改系统中众多的网络配置文件。如/etc/interfaces、/etc/hosts,/etc/resolv.conf 等等。
2.配置IP地址
1.IP地址
IP地址包括三部分:Internet网络号(Net-ID)、子网号(Subnet-ID)和主机号(Host-ID)。
2.配置IP地址
接入网络的计算机主机依靠IP地址,惟一地标识其在网络中的身份,因此为主机配置IP地址是接入网络的关键。
配置IP地址的方法有两种:
1.配置静态IP:在主机进入网络之前,事先为主机设置固定的IP地址;
2.配置动态IP:选择DHCP网络服务,在主机进入网络之后,动态随机获取IP地址。
3.网络相关命令
1.Ifconfig命令
ifconfig是GNU/Linux中配置网卡的基本命令,包含在net-tools软件包中。它可用于显示或设置网卡的配置,
如IP地址、子网掩码、最大分组传输数、IO端口等,还可以启动或禁用网卡。
ifconfig命令有以下两种格式:
ifconfig [interface]
ifconfig interface [aftype] option | address…
第一种格式用于查看当前系统的网络配置情况;
第二种格式用于配置网卡,包括添加、删除网卡,以及绑定多个IP地址等。
2.ping命令
1.ping(Packet Internet Groper)命令可能是最有名气的网络连接检测工具。
它使用了Internet控制报文协议(ICMP)回送请求与回送应答报文,测试两个主机之间的连通性。该命令的一般格式如下所示。
2.ping命令测试的远程主机,既可用域名,也可用IP地址标识。
ping [DomainName | IP-address]
3.可以使用该命令来判断主机与远程主机是否可达,或之间的网络是否拥塞。min/avg/max/mdev是ping命令的完成测试后的统计结果,
分别表示最小响应时间/平均响应时间/最大响应时间/响应时间方差。这些指标用于反应网络的联通程度。
linux@ubuntu:~$ ping www.ustb.edu.cn
4.ping命令执行时,会持续不断地向目的主机发送ICMP包。在得到对方的应答后,显示每次连接的统计数据,直到用Ctrl+C组合键中断执行。
但是,目前很多主机通过设置防火墙,对ping命令不予应答。在这种情况下,ping命令由于不停地发送测试数据包,又得不到返回任何结果,而致使ping命令僵死。
不过,使用-c参数设置发送测试数据包的次数,以便在有限时间内完成测试。
linux@ubuntu:~$ ping -c 3 www.google.com
PING www-china.l.google.com (66.249.89.99) 56(84) bytes of data.
--- www-china.l.google.com ping statistics ---
3.nslookup命令
使用nslookup命令可以查看当前系统所使用的DNS服务器的IP地址。
二、shell 编程
Shell 是一个命令解释权,它为用户提供了一个向 Linux 内核发送请求以便运行程序界面系统级程序,用户可以用 Shell 来启动、挂起、停止甚至是编写一些程序。
2.1 shell 脚本的基础知识
1.shell脚本的本质
编译型语言/解释型语言
shell脚本语言是解释型语言
shell脚本的本质:shell命令的有序集合
2.shell 编程的基本过程
基本过程分为三步:
step1. 建立 shell 文件
包含任意多行操作系统命令或shell命令的文本文件;
step2. 赋予shell文件执行权限
用chmod命令修改权限;
step3. 执行shell文件
直接在命令行上调用shell程序.
shell 编程的基本过程分为三步:
step1. 建立 shell 文件
包含任意多行操作系统命令或shell命令的文本文件;
step2. 赋予shell文件执行权限
用chmod命令修改权限;
step3. 执行shell文件
直接在命令行上调用shell程序.
示例:
step1: 建立shell文件 (可用任何建立文本文件的方法)
$ cat prog1.sh
date
Step2: 赋予执行权限: (初始文本文件无执行权限)
$ chmod 740 prog1.sh
Step3: 执行该shell程序
$ prog1.sh
prog1.sh: not found
(shell在标准搜索路径中找不到prog1.sh)
Step4: 指定路径或修改环境变量PATH后执行shell程序
$ ./prog1.sh
2024年 11月 18日 星期一 14:52:57 CST
2.2 shell 变量
shell允许用户建立变量存储数据,但不支持数据类型(整型、字符、浮点型),将任何赋给变量的值都解释为一串字符。
1.用户自定义变量
1) 在shell编程中通常使用全大写变量,方便识别
$ COUNT=1
2) 变量的调用:在变量前加$
$ echo $HOME
3) Linux Shell/bash从右向左赋值
$Y=y
$ X=$Y
$ echo $X
y
4) 使用unset命令删除变量的赋值
2.Shell 环境变量
HOME: /etc/passwd文件中列出的用户主目录
IFS:Internal Field Separator, 默认为空格,tab及换行符
PATH :shell搜索路径
PS1,PS2:默认提示符($)及换行提示符(>)
TERM:终端类型,常用的有vt100,ansi,vt200,xterm等
3.位置变量
$0 与键入的命令行一样,包含脚本文件名
$1,$2,……$9 分别包含第一个到第九个命令行参数
$# 包含命令行参数的个数
$@ 包含所有命令行参数:“$1,$2,……$9”
$? 包含前一个命令的退出状态
$* 包含所有命令行参数:“$1,$2,……$9”
$$ 包含正在执行进程的ID号
2.3 shell 程序和语句
shell 程序由零或多条shell语句构成。 shell语句包括三类:说明性语句、功能性语句和结构性语句。
2.3.1 说明性语句
以#号开始到该行结束,不被解释执行(注释行)
2.3.2 功能性语句
任意的shell命令、用户程序或其它shell程序。read、expr命令、test语句。
read:
案例一:
read从标准输入读入一行, 并赋值给后面的变量,其语法为:
read var # 把读入的数据全部赋给var
read var1 var2 var3 # 把读入行中的第一个单词(word)赋给var1, 第二个单词赋给var2, ……把其余所有的词赋给最后一个变量.
如果执行read语句时标准输入无数据, 则程序在此停留等侯, 直到数据的到来或被终止运行。
expr命令:算术运算命令expr主要用于进行简单的整数运算,包括加(+)、减(-)、乘(\*)、整除(/)和求模(%)等操作。
$ expr 12 + 5 \* 3
27
$ expr 3 - 8 / 2
-1
$ num=9
$ sum=`expr $num \* 6 `
$ echo $sum
54
test语句:test语句可测试三种对象:字符串、整数、文件属性。每种测试对象都有若干测试操作符。
例如:
1.test "$answer" = "yes" // 变量answer的值是否为字符串yes
2.test $num –eq 18 // 变量num的值是否为整数18
3.test -d tmp // 测试tmp是否为一个目录名
1)字符串测试
s1 = s2 测试两个字符串的内容是否完全一样
s1 != s2 测试两个字符串的内容是否有差异
-z s1 测试s1 字符串的长度是否为0
-n s1 测试s1 字符串的长度是否不为0
2)整数测试
a -eq b 测试a 与b 是否相等
a -ne b 测试a 与b 是否不相等
a -gt b 测试a 是否大于b
a -ge b 测试a 是否大于等于b
a -lt b 测试a 是否小于b
a -le b 测试a 是否小于等于b
3)文件测试
-d name 测试name 是否为一个目录
-e name 测试一个文件是否存在
-f name 测试name 是否为普通文件
-L name 测试name 是否为符号链接
-r name 测试name 文件是否存在且为可读
-w name 测试name 文件是否存在且为可写
-x name 测试name 文件是否存在且为可执行
-s name 测试name 文件是否存在且其长度不为0
f1 -nt f2 测试文件f1 是否比文件f2 更新
f1 -ot f2 测试文件f1 是否比文件f2 更旧
2.3.3 结构性语句
主要根据程序的运行状态、输入数据、变量的取值、控制信号以及运行时间等因素来控制程序的运行流程。 主要包括:条件测试语句(两路分支)、多路分支语句、循环语句、循环控制语句和后台执行语句等。
(1)条件语句 if…then…fi
if [ 条件判断式 ];then
程序
fi
# 或者(推荐)
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
fi
1.如果表达式为真, 则执行命令表中的命令; 否则退出if语句, 即执行fi后面的语句。
2.if和fi是条件语句的语句括号, 必须成对使用;
3.命令表中的命令可以是一条, 也可以是若干条。
案例1: $1
是一个特殊的变量,它代表传递给脚本的第一个命令行参数。当你在命令行中运行一个脚本,并在脚本名后面添加了一些参数时,这些参数会被存储在 $1
、$2
、$3
等变量中,其中 $1
是第一个参数,$2
是第二个参数,以此类推。
#!/bin/bash
if [ $1 -ge 60 ]
then
echo "及格"
elif [ $1 -lt 60 ]
then
echo "不及格"
fi
案例2:
例子: shell程序prog3.sh, 用法为:
./prog3.sh file
内容如下: #The statement of if…then…else…fi
if [-d $1]
then
echo "$1 is a directory"
exit (退出当前的shell程序)
else
if [-f $1]
then
echo "$1 is a common file"
else
echo "unknown"
fi
fi
运行prog3.sh程序:
$ ./prog3.sh backup
backup is a directory
$ ./prog3.sh prog1
prog1 is a common file
$ ./prog3.sh abc
unknown
prog3.sh是对prog2.sh的优化, 逻辑结构更加清晰合理!
(2)多路分支语句
多路分支语句: case…esac
多路分支语句case用于多重条件测试, 语法结构清晰自然. 其语法为:
结构:
case 字符串变量 in
模式1)
命令表1
;;
模式2 | 模式3)
命令表2
;;
……
模式n)
命令表n
;;
esac
注:
1)case语句只能检测字符串变量
2)各模式中可用文件名元字符,以右括号结束
3)一次可以匹配多个模式用“|”分开
4)命令表以单独的双分号行结束,退出case语句
5)模式 n常写为字符* 表示所有其它模式
6)最后一个双分号行可以省略
案例:使用 case
语句来检查用户输入的文件名,并根据输入执行不同的操作。
# The statement of case…esac
实例程序prog4.sh检查用户输入的文件名, 用法为:
./prog4.sh string_name
if [$# -eq 0] # 脚本首先检查是否有参数传递给它($# 是传递给脚本的参数数量)
then
echo "No argument is declared" # 如果没有参数,输出提示信息
exit # 退出脚本
fi
case $1 in
file1)
echo "User selects file1"
;;
file2)
echo "User selects file2"
;;
*)
echo "You must select either file1 or file2!"
;;
esac
(3)循环语句
1.循环语句for
当循环次数已知或确定时,使用for循环语句来多次执行一条或一组命令。循环体由语句括号do和done来限定。格式为:
for 变量名 in 单词表
do
命令表
done
变量依次取单词表中的各个单词, 每取一次单词, 就执行一次循环体中的命令.
循环次数由单词表中的单词数确定. 命令表中的命令可以是一条, 也可以是由分号或换行符分开的多条。
如果单词表是命令行上的所有位置参数时, 可以在for语句中省略 “in 单词表” 部分。
2.循环语句while
语法结构为:
while 命令或表达式
do
命令表
done
1)while语句首先测试其后的命令或表达式的值,如果为真,就执行一次循环体中的命令,
然后再测试该命令或表达式的值,执行循环体,直到该命令或表达式为假时退出循环。
2)while语句的退出状态为命令表中被执行的最后一条命令的退出状态。
3.循环控制语句
break 和 continue
break n 则跳出n层;
continue语句则马上转到最近一层循环语句的下一轮循环上,
continue n则转到最近n层循环语句的下一轮循环上.
案例1(for):将当前目录下的所有文件复制到 $HOME/backup
子目录下。如果提供了特定的文件名作为参数,它只会复制那个特定的文件。
#!/bin/bash
# 使用语法为: ./prog5.sh [filename]
if [ ! -d $HOME/backup ]; then # 检查 $HOME/backup 目录是否存在,如果不存在则创建
mkdir $HOME/backup
fi
flist=`ls` # 获取当前目录下的所有文件列表
for file in $flist # 遍历文件列表
do
# 如果提供了一个参数
if [ $# = 1 ]; then
# 如果提供的参数与当前文件名匹配
if [ $1 = $file ]; then
echo "$file found"; exit
fi
else
# 复制文件到 $HOME/backup 目录
cp $file $HOME/backup
echo "$file copied"
fi
done
# 输出备份完成的消息
echo "***Backup Completed***"
案例2(while):是一个用于批量生成空白文件的 Bash 脚本。脚本接受两个参数:第一个参数是文件名前缀,第二个参数是生成文件的数量。如果没有提供第二个参数,则默认生成5个文件。
#!/bin/bash
# 用法为: prog6 file 6
# 检查参数数量是否为2
if [ $# -eq 2 ]; then
loop=$2 # 根据命令行的第二个参数来确定循环的次数
else
loop=5
fi
i=1
# 使用 while 循环生成文件
while [ $i -lt $loop ]; do
> $1$i # 建立以第一个参数指定的文件名前缀,例如以“file”开头,变量i的值结尾的空文件名
i=`expr $i + 1` # 增加循环计数器
done
案例3:break 和 continue 。用于处理不确定数量的参数,范围是1到10个正整数。脚本会过滤出其中的偶数,并在最后输出所有的偶数。运行脚本,传递1到10个正整数作为参数:./prog7 1 2 3 4 5
将输出偶数:Even numbers: 2 4
。
#!/bin/bash
# 用法为: prog7 整数 整数 整数 …
# 检查参数数量是否为0
if [ $# -eq 0 ]; then
echo "Numeric arguments required"
exit
fi
# 检查参数数量是否超过10
if [ $# -gt 10 ]; then
echo "Only ten arguments allowed"
exit
fi
output=""
for number in "$@"; do
count=`expr $number % 2`
if [ $count -eq 1 ]; then
continue
else
output="$output $number"
fi
done
echo "Even numbers: $output"
2.4 函数的调用
函数:
和其它编程语言一样,Shell 编程有系统函数和自定义函数。
函数调用格式:
方式1:
value_name=`function_name [arg1 arg2 … ]`
函数的所有标准输出都传递给了主程序的变量
方式2:
function_name [arg1 arg2 … ]
echo $?
获取函数的返回的状态
案例: 用于检查是否有指定的用户已登录系统。脚本定义了一个名为 check_user
的函数,该函数接受一个参数(用户名),并返回该用户是否在线的状态。主循环部分不断提示用户输入用户名,并使用 check_user
函数检查用户状态。
#!/bin/bash # 告诉系统使用 /bin/bash 路径下的 Bash 解释器来执行脚本
check_user() { # 查找已登录的指定用户
user=`who | grep $1 | wc -l`
if [ $user -eq 0 ]; then
return 0 # 未找到指定用户
else
return 1 # 找到指定用户
fi
}
while true # MAIN, Main, main: program begin here
do
echo "Input username: \c"
read uname
check_user $uname # 调用函数, 并传递参数uname
if [ $? -eq 1 ] # $?为函数返回值
then
echo "user $uname online"
else
echo "user $uname offline"
fi
done