Shell基础与编程
Shell基础
1. Shell概述
-
Shell是什么
- Shell是一个命令行解释器,它为用户提供 了一个向Linux内核发送请求以便运行程 序的界面系统级程序,用户可以用Shell来 启动、挂起、停止甚至是编写一些程序。
- Shell还是一个功能相当强大的编程语言, 易编写,易调试,灵活性较强。Shell是解 释执行的脚本语言,在Shell中可以直接调 用Linux系统命令。
-
Shell的分类
-
Bourne Shell:从1979起Unix就开始使用 Bourne Shell,Bourne Shell的主文件名为 sh。
-
C Shell: C Shell主要在BSD版的Unix系 统中使用,其语法和C语言相类似而得名
Shell的两种主要语法类型有Bourne和C, 这两种语法彼此不兼容。Bourne家族主要 包括sh、ksh、Bash、psh、zsh;C家族主 要包括:csh、tcsh
Bash: Bash与sh兼容,现在使用的Linux 就是使用Bash作为用户的基本Shell。
-
-
Linux支持的Shell
/etc/shells
会显示:/bin/sh /bin/bash /sbin/nologin /bin/tcsh /bin/csh
都是Linux支持的Shell
2. Shell脚本的执行方式
echo输出命令
echo [选项] [输出内容]
-e: 支持反斜线控制的字符转换
下表为控制符的作用:
控制字符 | 作用 |
---|---|
\ | 输出\本身 |
\a | 输出警告音 |
\b | 退格键,也就是向左删除键 |
\c | 取消输出行末的换行符。和“-n”选项一致 |
\e | ESCAPE键 |
\f | 换页符 |
\n | 换行符 |
\r | 回车键 |
\t | 制表符,也就是Tab键 |
\v | 垂直制表符 |
\0nnn | 按照八进制ASCII码表输出字符。其中0为数字零,nnn是三位八进制数 |
\xhh | 按照十六进制ASCII码表输出字符。其中hh是两位十六进制数 |
例子:
- echo -e “ab\bc”
输出:ac 删除左侧字符
- echo -e "a\tb\tc\nd\te\tf"
输出:
a b c
d e f 制表符与换行符
- echo -e “\x61\t\x62\t\x63\n\x64\t\x65\t\x66”
输出:
a b c
d e f 按照十六进制ASCII码也同样可以输出
- echo -e "\e[1;31m abcd \e[0m"
输出:
红色的abcd
因为\e[1 表示开启颜色区别 \e[0m 表示结束颜色区别 31m表示红色 还有其他:
30m=黑色,31m=红色,32m=绿色,33m=黄色,34m=蓝色,35m=洋红,36m=青色,37m=白色
脚本
vi hello.sh
\#!/bin/Bash
\#The first program
\#Author: yangyang (E-mail: 1771566679@qq.com
vi)
echo -e ‘Hello World!’
注意:在这一段脚本中,#!/bin/Bash这一句是个例外,他并不是注释,是标识,不能省略,说明以下语句是Shell脚本,‘Hello World!’如果要加感叹号就得是单引号,如果没有感叹号才可以是双引号,这感叹号有意义。
脚本执行
-
赋予执行权限,直接运行
chmod 755 hello.sh ./hello.sh
-
通过Bash调用执行脚本
bash hello.sh不需要执行权限就可以执行 所有程序必须用绝对路径或者相对路径执行
有一个操作:
如果从Windows里面拷贝一个脚本到Linux 虽然有的时候格式一样但是还是会报错,这便是因为两个系统中脚本的格式不同,比如Windows中的回车在脚本中用^M$表示,而Linux中为$,(可以用cat -A [文件名] 来查询)所以需要转变,此时用到一个命令:dos2unix [文件名]
转换后,Linux就可以执行啦,通过没有这个命令可以使用yum安装
3. Bash的基本功能
3.1 历史命令与命令补全
历史命令
history [选项] [历史命令保存文件]
- c: 清空历史命令
- w: 把缓存中的历史命令写入历史命令保存文件 ~/.bash_history
历史命令默认会保存1000条,可以在环境 变量配置文件/etc/profile中进行修改
找到HISTSIZE=1000进行修改,随意修改到100000条都可以,修改之后重启使配置文件生效
历史命令的调用
- 使用上、下箭头调用以前的历史命令
- 使用“!n”重复执行第n条历史命令
- 使用“!!”重复执行上一条命令
- 使用“!字串”重复执行最后一条以该字 串开头的命令
命令与文件补全
在Bash中,命令与文件补全是非常方便与常用的功能,我们只要在输入命令或文件时,按“Tab”键就会自动进行补全
3.2 命令别名与常用快捷键
- 命令别名
- alias 别名=‘原命令’ 设定命令别名
- alias 查询命令别名
- 命令执行时顺序
- 1 第一顺位执行用绝对路径或相对路径执行 的命令。
- 2 第二顺位执行别名。
- 3 第三顺位执行Bash的内部命令。
- 4 第四顺位执行按照$PATH环境变量定义的 目录查找顺序找到的第一个命令。
- 让别名永久生效
vi /root/.bashrc
-
删除别名
unalias 别名
Bash常用快捷键
下表:
快捷键 | 作用 |
---|---|
ctrl+a | 把光标移动到命令行开头。如果我们输入的命令过长,想要把光标移 动到命令行开头时使用。 |
ctrl+e | 把光标移动到命令行结尾。 |
ctrl+c | 强制终止当前的命令。 |
ctrl+l | 清屏,相当于clear命令。 |
ctrl+u | 删除或剪切光标之前的命令。我输入了一行很长的命令,不用使用退 格键一个一个字符的删除,使用这个快捷键会更加方便 |
ctrl+k | 删除或剪切光标之后的内容。 |
ctrl+y | 粘贴ctrl+U或ctrl+K剪切的内容。 |
ctrl+r | 在历史命令中搜索,按下ctrl+R之后,就会出现搜索界面,只要输入 搜索内容,就会从历史命令中搜索。 |
ctrl+d | 退出当前终端。 |
ctrl+z | 暂停,并放入后台。这个快捷键牵扯工作管理的内容,我们在系统管 理章节详细介绍。 |
ctrl+s | 暂停屏幕输出。 |
ctrl+q | 恢复屏幕输出。 |
其中标记的为重点快捷键,需要熟练使用
注意:ctrl+z 快捷键一定要谨慎使用,如果使用的多了,系统会占用大量存储空间来存放暂停的数据,用多了系统会变卡!!!
3.3 输入输出重定向
- 标准输入输出
设备 | 设备文件名 | 文件描述符 | 类型 |
---|---|---|---|
键盘 | /dev/stdin | 0 | 标准输入 |
显示器 | /dev/sdtout | 1 | 标准输出 |
显示器 | /dev/sdterr | 2 | 标准错误输出 |
- 输出重定向:就是改变输出方向,比如由屏幕输出到文件,非常有用
类型 | 符号 | 作用 |
---|---|---|
标准输出重定向 | 命令 > 文件 | 以覆盖的方式,把命令的正确输出输 出到指定的文件或设备当中。 |
标准输出重定向 | 命令 >> 文件 | 以追加的方式,把命令的 正确输出输出到指定的文 件或设备当中。 |
标准错误输出重定向 | 错误命令 2>文件 | 以覆盖的方式,把命令的 错误输出输出到指定的文 件或设备当中。 |
标准错误输出重定向 | 错误命令 2>>文件 | 以追加的方式,把命令的错误输出输出到指定的文件或设备当中。 |
注意:在输入报错文件中 2 和 >> 必选连着写,标准错误输出不常用
类型 | 符号 | 作用 |
---|---|---|
正确输出和错误输出同时保存 | 命令 > 文件 2>&1 | 以覆盖的方式,把正确输 出和错误输出都保存到同 一个文件当中。 |
正确输出和错误输出同时保存 | 命令 >> 文件 2>&1 | 以追加的方式,把正确输 出和错误输出都保存到同 一个文件当中。 |
正确输出和错误输出同时保存 | 命令 &>文件 | 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 &>>文件 | 以追加的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 >> 文件1 2>>文件2 | 把正确的输出追加到文件1中,把错误的输出追加到文件2中。 |
注意: 命令 >> 文件 2>&1 ,命令 &>>文件 两种保存都一样,只不过是格式不同
有一个用法:命令 &>/dev/unll 不管命令是否正确,直接丢人这个文件夹,不保存任何数据,在写 shell脚本时有用
-
输入重定向:不通过键盘输入,通过文件输入,在实际中用的不多,用在给源码包打补丁
wc [选项] [文件名] - -c 统计字节数 - -w 统计单词数 - -l 统计行数
用法:
命令 < 文件 把文件作为命令的输入
命令 << 标识符 一直输入,直到输入标识停止输入把标识符之间内容作为命令的输入
3.4 多命令顺序执行与管道符 多命令顺序执行
多命令执行符 | 格式 | 作用 |
---|---|---|
; | 命令1 ;命令2 | 多个命令顺序执行,命令之间没有任何逻辑联系,就算第一条报错,第二条也会执行 |
&& | 命令1 && 命令2 | 逻辑与当命令1正确执行,则命令2才会执行 当命令1执行不正确,则命令2不会执行 |
|| | 命令1 || 命令2 | 逻辑或当命令1 执行不正确,则命令2才会执行 当命令1正确执行,则命令2不会执行 |
-
磁盘文件复制:
dd if=输入文件 of=输出文件 bs=字节数 count=个数 - if=输入文件 指定源文件或源设备 - of=输出文件 指定目标文件或目标设备 - bs=字节数 指定一次输入/输出多少字节,即把这些字节看做 一个数据块 - count=个数 指定输入/输出多少个数据块 这条命令可以把系统文件,磁盘都复制了,非常强大 例子: date ; dd if=/dev/zero of=/root/testfile bs=1k count=100000 ; date
-
管道符
命令1 | 命令2
注意:命令1的正确输出作为命令2的操作对象
颜色显示
grep [选项] “搜索内容” 文件名- -i: 忽略大小写
- -n: 输出行号
- -v: 反向查找
- –color=auto 搜索出的关键字用颜色显示
3.5 通配符与其他特殊符号
通配符
通配符 | 作用 |
---|---|
? | 匹配一个任意字符 |
* | 匹配0个或任意多个任意字符,也就是可以匹配任何内容 |
[] | 匹配中括号中任意一个字符。例如:[abc]代表一定匹配 一个字符,或者是a,或者是b,或者是c。 |
[-] | 匹配中括号中任意一个字符,-代表一个范围。例如:[a-z] 代表匹配一个小写字母。 |
[^] | 逻辑非,表示匹配不是中括号内的一个字符。例如:[^0- 9] 代表匹配一个不是数字的字符。 |
Bash中其他特殊符号
符号 | 作用 |
---|---|
‘’ | 单引号。在单引号中所有的特殊符号,如“$”和“`”(反引号)都 没有特殊含义。 |
“” | 双引号。在双引号中特殊符号都没有特殊含义,但是“$”、“`” 和“\”是例外,拥有“调用变量的值”、“引用命令”和“转义符”的特殊含义。 |
`` | 反引号。反引号括起来的内容是系统命令,在Bash中会先执行它。 和$()作用一样,不过推荐使用$(),因为反引号非常容易看错。 |
$() | 和反引号作用一样,用来引用系统命令。 |
# | 在Shell脚本中,#开头的行代表注释。 |
$ | 用于调用变量的值,如需要调用变量name的值时,需要用$name 的方式得到变量的值。 |
\ | 转义符,跟在\之后的特殊符号将失去特殊含义,变为普通字符。 如$将输出“$”符号,而不当做是变量引用。 |
4. Bash的变量
4.1 用户自定义变量
-
什么是变量:
变量是计算机内存的单元,其中存放的值可以改变。当Shell脚本需要保存一些信息 时,如一个文件名或是一个数字,就把它 存放在一个变量中。每个变量有一个名字 ,所以很容易引用它。使用变量可以保存 有用信息,使系统获知用户相关设置,变量也可以用于保存暂时信息。 -
变量设置规则:
- 变量名称可以由字母、数字和下划线组成 ,但是不能以数字开头。如果变量名是 “2name”则是错误的。
- 在Bash中,变量的默认类型都是字符串型 ,如果要进行数值运算,则必需指定变量类型为数值型。
- 默认变量类型全都是字符串型,和其他语言不太一样
- 变量用等号连接值,等号左右两侧不能有空格。
- 变量的值如果有空格,需要使用单引号或双引号包括。
- 在变量的值中,可以使用“\”转义符。
- 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含 “$变量名”或用${变量名}包含。
- 如果是把命令的结果作为变量值赋予变量 ,则需要使用反引号或$()包含命令。
- 环境变量名建议大写,便于区分。
-
变量的分类:
- 用户自定义变量
- 环境变量:这种变量中主要保存的是和系统操作环境相关的数据。
- 位置参数变量:这种变量主要是用来向脚本当 中传递参数或数据的,变量名不能自定义,变量作用是固定的。
- 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
-
本地变量(用户自定义变量)
变量定义例子: name=“yang yang” + 变量叠加 aa=123 aa="$aa"456 aa=${aa}789 + 变量调用 echo $变量名 + 变量查看 set + 变量删除 unset 变量名
4.2 环境变量
-
环境变量:
用户自定义变量只在当前的Shell中生效, 而环境变量会在当前Shell(就是当前这个使用操作终端)和这个Shell的所 有子Shell当中生效。如果把环境变量写入相应的配置文件,那么这个环境变量就会在所有的Shell中生效 -
设置环境变量:
- export 变量名=变量值 申明变量
- env 查询变量
- echo $变量名 变量调用
- unset 变量名 删除变量
- pstree 树形显示进程数
没有这条命令可以执行以下命令下载:
yum -y install psmisc
yum provides /命令 查看没有的命令的安装包 配合yum -y install使用
-
系统常见环境变量
环境变量名称 描述 PATH 系统查找命令的路径 PS1 定义系统提示符的变量 用来改[root@localhost ~]# 这个显示 \d 显示日期,格式为“星期 月 日” \h 显示简写主机名。如默认主机名“localhost” \t 显示24小时制时间,格式为“HH:MM:SS” \T 显示12小时制时间,格式为“HH:MM:SS” \A 显示24小时制时间,格式为“HH:MM” \u 显示当前用户名 \w 显示当前所在目录的完整名称 \W 显示当前所在目录的最后一个目录 # 执行的第几个命令 $ 提示符。如果是root用户会显示提示符为“#”,如果是普通用户 会显示提示符为“$” -
PATH:系统查找命令的路径
这便是输入命令之前不用输入绝对路径的根本原因,系统会提前在PATH环境变量里的所有路径中查询一遍有没有你输入的命令,找到之后直接执行
如果你想直接执行shell脚本,不加绝对路径,直接写入PATH环境变量,使用叠加例子: echo $PATH PATH="$PATH":/root/sh PATH变量叠加 此后,/root/sh路径里面的执行文件都可以在任意目录下直接执行,不过是临时生效
-
PS1:定义系统提示符的变量 用来改[root@localhost ~]# 这个显示
-
\d:显示日期,格式为“星期 月 日”
-
\h:显示简写主机名。如默认主机名“localhost”
-
\t:显示24小时制时间,格式为“HH:MM:SS”
-
\T:显示12小时制时间,格式为“HH:MM:SS”
-
\A:显示24小时制时间,格式为“HH:MM”
-
\u:显示当前用户名
-
\w:显示当前所在目录的完整名称
-
\W:显示当前所在目录的最后一个目录
-
:执行的第几个命令
-
$:提示符。如果是root用户会显示提示符为“#”,如果是普通用户 会显示提示符为“$”
-
4.3 位置参数变量
位置参数变量
位置参数变量 | 作用 |
---|---|
$n | n为数字,$0代表命令本身,$1-9 代 表 第 一 到 第 九 个 参 数 , 十 以 上 的 参 数 需 要 用 大 括 号 包 含 , 如 9代表第一 到第九个参数,十以上的参数需要用大括号 包含,如9代表第一到第九个参数,十以上的参数需要用大括号包含,如{10}. |
$* | 这个变量代表命令行中所有的参数,$*把所 有的参数看成一个整体 |
$@ | 这个变量也代表命令行中所有的参数,不过 $@把每个参数区分对待 |
$# | 这个变量代表命令行中所有参数的个数 |
例子脚本:
-
$n的例子:
#!/bin/bash num1=$1 num2=$2 sum=$(( $num1 + $num2)) #变量sum的和是num1加num2 echo $sum #打印变量sum的值
-
$*,$@,$#的例子:
#!/bin/bash echo “A total of $# parameters” #使用$#代表所有参数的个数 echo “The parameters is: $\*” #使用$\*代表所有的参数 echo “The parameters is: $@” #使用$@也代表所有参数
-
$*与$@的区别例子:
#!/bin/bash for i in “$\*” \**#$\*中的所有参数看成是一个整体,所以这个for循环只会循环一次\** do echo “The parameters is: $i” done x=1 for y in “$@” \**#$@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次\** do echo “The parameter$x is: $y” x=$(( $x +1 )) done
4.4 预定义变量
- 预定义变量
预定义变量 | 作用 |
---|---|
$? | 最后一次执行的命令的返回状态。如果这个变 量的值为0,证明上一个命令正确执行;如果 这个变量的值为非0(具体是哪个数,由命令 自己来决定),则证明上一个命令执行不正确 了。 |
$$ | 当前进程的进程号(PID) |
$! | 后台运行的最后一个进程的进程号(PID) |
- 例子:
#!/bin/bash
\#Author: yangyang (E-mail: 1771566679@qq.com)
echo “The current process is $$”
\#输出当前进程的PID。
\#这个PID就是variable.sh这个脚本执行时,生成的进程的PID
find /root -name hello.sh &
\#使用find命令在root目录下查找hello.sh文件 #符号&的意思是把命令放入后台执行,工作管理在系统管理章节会详细介绍
echo "The last one Daemon process is $!"
- 接受键盘输入
read [选项] [变量名]
- -p “提示信息”:在等待read输入时,输出提示信息
- -t 秒数: read命令会一直等待用户输入,使用 此选项可以指定等待时间
- -n 字符数:read命令只接受指定的字符数,就会执行
- -s: 隐藏输入的数据,适用于机密信息的输入
5. Bash的运算符
5.1 数值运算与运算符
- declare声明变量类型
declare [+/-][选项] 变量名
-: 给变量设定类型属性
+: 取消变量的类型属性
-i: 将变量声明为整数型(integer) set-x: 将变量声明为环境变量
-p: 显示指定变量的被声明的类型
-
数值运算
-
数值运算—方法1
aa=11 bb=22 给变量aa和bb赋值 declare -i cc=$aa+$bb
-
expr或let数值运算工具—方法2
aa=11 bb=22 给变量aa和bb赋值 dd=$(expr $aa + $bb) dd的值是aa和bb的和。注意“+”号左右两 侧必须有空格 let与expr一样
-
“$((运算式))”或“$[运算式]” —方法3
aa=11 bb=22 给变量aa和bb赋值 ff=$(( $aa+$bb )) gg=$[ $aa+$bb ]
运算符
运算符优先级表:
优先级 | 运算符 | 说明 |
---|---|---|
13 | -, + | 单目负、单目正 |
12 | !, ~ | 逻辑非、按位取反或补码 |
11 | *,/, % | 乘、除、取模 |
10 | +, - | 加、减 |
9 | << , >> | 按位左移、按位右移 |
8 | < =, > =, < , > | 小于或等于、大于或等于、小于、大于 |
7 | == , != | 等于、不等于 |
6 | & | 按位与 |
5 | ^ | 按位异或 |
4 | | | 按位或 |
3 | && | 逻辑与 |
2 | || | 逻辑或 |
1 | =,+=,-=,*=,/=,%=,&=, ^=,赋值、运算且赋值 |=, <<=, >>= |
例子:
- aa=$(( (11+3)\*3/2 ))
虽然乘和除的优先级高于加,但是通过小括号可以调整运算优先级
- bb=$(( 14%3 ))
14不能被3整除,余数是2
- cc=$(( 1 && 0 ))
逻辑与运算只有想与的两边都是1,与的结果才是1,否则与的结果是0
- dd=$(( 1 || 0 ))
逻辑或运算只要有一边是1,或的结果就是1,两边都为0,或的结果才是0
5.2 变量测试与内容替换
用来测试一个变量到底有没有设置,测试表:
变变量置换方式 | 变量y没有设置 | 变量y为空值 | 变量y设置值 |
---|---|---|---|
x=$ | x=新值 | x为空 | x=$y |
x=$ | x=新值 | x=新值 x=$y | |
x=$ | x为空 | x=新值 | x=新值 |
x=$ | x为空 | x为空 | x=新值 |
x=$ | x=新值 y=新值 | x为空 y值不变 | x=$y y值不变 |
x=$ | x=新值 y=新值 | x=新值 y=新值 | x=$y y值不变 |
x=$ | 新值输出到标准错误输出(就是屏幕) | x为空 | x=$y |
x=$ | 新值输出到标准错误输出 | 新值输出到标准错误输 | x=$y |
例子:
测试x=${y-新值} 测试y变量存不存在
- unset y 删除变量y
x=${y-new} 进行测试
echo $x
显示new,y变量不存在
因为变量y不存在,所以x=new
- y="" 给变量y赋值为空
x=${y-new} 进行测试
echo $x
显示空,y为空值
- y=old 给变量y赋值
x=${y-new} 进行测试
echo $x
显示old ,y变量存在且有值
在用到的时候查询就好,不需要死记硬背。这个表是在写脚本的时候给电脑程序看的,人不参与其中
6. Bash的运算符
6.1 环境变量配置文件简介
source命令
- source 配置文件 强制使配置文件在修改之后生效,不需要重启
- . 配置文件 和source 配置文件的作用是一样的
环境变量配置文件简介
环境变量配置文件中主要是定义对系统的操作环境生效的系统默认环境变量,比如 PATH、HISTSIZE、PS1、HOSTNAME等 默认环境变量。
配置文件保存位置
- /etc/profile
- /etc/profile.d/\*.sh 指/etc/profile.d/下所有的.sh结尾的文件
- ~/.bash_profile
- ~/.bashrc
- /etc/bashrc
/etc下的环境变量配置文件是针对所有用户都有效的
而~下的只是对root用户的家目录下有效
6.2 环境变量配置文件作用
以下几个环境变量的配置文件是最主要的:
- /etc/profile
- /etc/profile.d/*.sh 指/etc/profile.d/下所有的.sh结尾的文件
- ~/.bash_profile
- ~/.bashrc
- /etc/bashrc
环境变量配置文件调用顺序流程图
这些是在登陆的时候挨个调用,所以在这里面设置环境变量,登陆之后就会自动设置好
- 登陆输入密码之后,第一步是读取/etc/profile文件
/etc/profile的作用:
USER变量
LOGNAME变量
MAIL变量
PATH变量
HOSTNAME变量
HISTSIZE变量
umask
里面有以上环境变量的配置
- 接下来便调用/etc/profile.d/\*.sh文件
然后就是下面的文件,语言包文件,识别系统自带的语言
~/.bash_profile的作用
- 调用了~/.bashrc文件。
在PATH变量后面加入了“:$HOME/bin” 这个目录
~/.bashrc的作用
定义默认别名
- 调用/etc/bashrc
/etc/bashrc的作用
PS1变量
umask
PATH变量
- 调用/etc/profile.d/\*.sh文件
这一块就是进入界面以内,切换shell登陆方式,这种不需要密码,所以和前面的/etc/profile的作用不冲突
6.3 其他配置文件和登录信息
注销时生效的环境变量配置文件
- ~/.bash_logout
注销登陆时写入
其他配置文件
- ~/bash_history 历史命令文件
Shell登录信息
- 本地终端欢迎信息: /etc/issue
转义符 | 作用 |
---|---|
\d | 显示当前系统日期 |
\s | 显示操作系统名称 |
\l | 显示登录的终端号,这个比较常用。 |
\m | 显示硬件体系结构,如i386、i686等 |
\n | 显示主机名 |
\o | 显示域名 |
\r | 显示内核版本 |
\t | 显示当前系统时间 |
\u | 显示当前登录用户的序列号 |
- 远程终端欢迎信息: /etc/issue.net
- 转义符在/etc/issue.net文件中不能使用
- 是否显示此欢迎信息,由ssh的配置文件 /etc/ssh/sshd_config决定,加入“Banner /etc/issue.net”行才能显示(记得重启SSH服务)
登陆后欢迎信息:/etc/motd
不管是本地登录,还是远程登录,都可以显示此欢迎信息
Shell编程
1. 基础正则表达式
正则表达式与通配符
- 正则表达式用来在文件中匹配符合条件的 字符串,正则是包含匹配。grep、awk、 sed等命令可以支持正则表达式。
- 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。
基础正则表达式
元字符 | 作用 |
---|---|
* | 前一个字符匹配0次或任意多次。 |
. | 匹配除了换行符外任意一个字符。 |
^ | 匹配行首。例如:^hello会匹配以hello开头的行。 |
$ | 匹配行尾。例如:hello&会匹配以hello结尾的行。 |
[] | 匹配中括号中指定的任意一个字符,只匹配一个字符。 例如:[aoeiu] 匹配任意一个元音字母,[0-9] 匹配任意一位 数字, [a-z][0-9]匹配小写字和一位数字构成的两位字符。 |
[^] | 匹配除中括号的字符以外的任意一个字符。例如:[^0-9] 匹配 任意一位非数字字符,[^a-z] 表示任意一位非小写字母。 |
\ | 转义符。用于取消讲特殊符号的含义取消。 |
表示其前面的字符恰好出现n次。例如:[0-9]{4} 匹配4位数 字,[1][3-8][0-9]{9} 匹配手机号码。 | |
表示其前面的字符出现不小于n次。例如: [0-9]{2,} 表示两 位及以上的数字。 | |
表示其前面的字符至少出现n次,最多出现m次。例如: [a- z]{6,8} 匹配6到8位的小写字母。 |
-
*
前一个字符匹配0次,或任意多次- grep “a*” test_rule.txt 匹配所有内容,包括空白行 - grep “aa*” test_rule.txt 匹配至少包含有一个a的行 - grep “aaa*” test_rule.txt 匹配最少包含两个连续a的字符串 - grep “aaaaa*” test_rule.txt 则会匹配最少包含四个个连续a的字符串
-
.
匹配除了换行符外任意一个字符- grep “s…d” test_rule.txt “s…d”会匹配在s和d这两个字母之间一定有两个字符的单词 - grep “s.\*d” test_rule.txt 匹配在s和d字母之间有任意字符 - grep “.\*” test_rule.txt 匹配所有内容
-
^
匹配行首,$
匹配行尾- **grep “^M” test_rule.txt** **匹配以大写“M”开头的行** - **grep “n$” test_rule.txt** **匹配以小写“n”结尾的行** - **grep -n “^$” test_rule.txt** **会匹配空白行**
-
[]
匹配中括号中指定的任意一个 字符,只匹配一个字符- grep “s[ao]id” test_rule.txt 匹配s和i字母中,要不是a、要不是o - grep “[0-9]” test_rule.txt 匹配任意一个数字 - grep “^[a-z]” test_rule.txt 匹配用小写字母开头的行
-
[^]
匹配除中括号的字符以外的 任意一个字符- grep “^[^a-z]” test_rule.txt 匹配不用小写字母开头的行 - grep “^[^a-z A-Z]” test_rule.txt 匹配不用字母开头的行
-
\
转义符- grep “\.$” test_rule.txt 匹配使用“.”结尾的行 - “\{n\}”表示其前面的字符恰好出现n次 - grep “a\{3\}” test_rule.txt 匹配a字母连续出现三次的字符串 - grep “[0-9]\{3\}” test_rule.txt 匹配包含连续的三个数字的字符串 - “\{n,\}”表示其前面的字符出现不小于n次 - grep “^\[0-9]\{3,\}[a-z]” test_rule.txt 匹配最少用连续三个数字开头的行 - “\{n,m\}”匹配其前面的字符至少出现n次, 最多出现m次 - grep “sa\{1,3\}i” test_rule.txt 匹配在字母s和字母i之间有最少一个a,最多三个a
2. 字符截取命令
2.1 cut字段提取命令
cut [选项] 文件名
- -f 列号: 提取第几列
- -d 分隔符: 按照指定分隔符分割列
grep为提取行,cut提取列,而且cut提取的表格中,只能用制表符隔开不能用空格比如:
ID | Name | gender | Mark |
---|---|---|---|
1 | Li | M | 86 |
2 | Shen | M | 90 |
3 | Gao | M | 83 |
他们之间所有的都是拿Tab键隔开的,不是空格
- 提取多列时,用
,
隔开就可以
cut -f 2 student.txt
cut -f 2,3 student.txt - 有具体分割符时,也可以没有Tab键
cut -d “:” -f 1,3 /etc/passwd 以:为分隔符取1,3列 - 一般在使用cut命令的时候和管道符“|”连着使用
2.2 printf命令
printf ‘输出类型输出格式’ 输出内容
-
输出类型:
- %ns: 输出字符串。n是数字指代输出几个字符
- %ni: 输出整数。n是数字指代输出几个数字
- %m.nf: 输出浮点数。m和n是数字,指代输出的整数 位数和小数位数。如%8.2f代表共输出8位数, 其中2位是小数,6位是整数。
-
输出格式:
- \a: 输出警告声音
- \b: 输出退格键,也就是Backspace键
- \f: 清除屏幕
- \n: 换行
- \r: 回车,也就是Enter键
- \t: 水平输出退格键,也就是Tab键 \v: 垂直输出退格键,也就是Tab键
例子: printf %s 1 2 3 4 5 6 printf %s %s %s 1 2 3 4 5 6 printf ‘%s %s %s’ 1 2 3 4 5 6 printf ‘%s %s %s\n’ 1 2 3 4 5 6 只有最后一个会输出:shell 1 2 3 4 5 6 因为每有一个%s代表每几个字符输出一次 %s %s %s\n 代表没三个字符输出一次并且换行 在与cat命令结合使用的时候,需要用$()把cat命令扩起来,使用这种命令赋予变量的方式,才能正确输出文件内容,但是具体格式还得用%s\t 或者%s\n控制
-
printf主要在awk命令编程中使用
例子: vi student.txt ID Name PHP Linux MySQL Average 1 Liming 82 95 86 87.66 2 Sc 74 96 87 85.66 3 Gao 99 83 93 91.66
-
printf ‘%s’ $(cat student.txt) 不调整输出格式
-
printf ‘%s\t %s\t %s\t %s\t %s\t %s\t \n’ $(cat student.txt)
调整格式输出
在awk命令的输出中支持print和printf命令
- print: print会在每个输出之后自动加入一 个换行符(Linux默认没有print命令)
- printf: printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符
2.3 awk命令
awk命令也叫awk编程,可以识别非制表符的空格,用来解决cut命令解决不了的提取列工作,他是把需要提取的原文件一行一行扫描,扫描每一行中所需要点列,然后把它记录下来,在全部扫描完之后全部打印出来。
-
awk ‘条件1{动作1} 条件2{动作2}…’ 文件名
-
条件(Pattern):
一般使用关系表达式作为条件- x > 10 判断变量 x是否大于10
- x>=10 大于等于
- x<=10 小于等于
-
动作(Action):
-
格式化输出流程控制语句
例子: vi student.txt ID Name PHP Linux MySQL Average 1 Liming 82 95 86 87.66 2 Sc 74 96 87 85.66 3 Gao 99 83 93 91.66 awk ‘{printf $2 “\t” $6 “\n”}’ student.txt 其中$2代表第2列,$6代表第6列,他可以识别非制表符的空格,单引号里面直接大括号代表没有条件,只要是输入有内容全部符合,取第2列和第6列 df -h | awk '{print $1 “\t” $3}' 提取 df -h命令显示之后的内容中第一列和第三列
需要注意:printf 不可以自动换行,print 可以在末尾自动换行,但是在Linux系统中没有print命令,只有printf命令,但是在wak命令中两个都有,使用print可以少一个换行符。
-
BEGIN
BEGIN必须是大写,他是一个条件。-
例子:
awk ‘BEGIN{printf “This is a transcript \n” } {printf $2 “\t” $6 “\n”}’ student.txt
他会在打印出2,6行之前先输出一句话This is a transcript,它的作用是强者命令第一个执行他后面的语句,也可以指定分割符
-
-
FS内置变量
FS是用来指定分隔符的,FS=“:”就是指定:为分隔符- 例子:
cat /etc/passwd | grep “/bin/bash” |awk 'BEGIN {FS=":"} {printf $1 “\t” $3 “\n”}'
这是打印用户信息地一和第三列,为什么需要在{FS=":"} 前加BEGIN呢?
因为如果你不加BEGIN你会发现除了第一行,其他都已经按格式打印出来了,但是只有第一行会照原样输出,因为awk默认是空格为分隔符,他在执行这条命令的时候,第一行数据已经被扫描了,所以来不及修改格式,但是加了BEGIN,他会第一步强制先把默认分隔符修改了。 - 例子:
-
关系运算符
cat student.txt | grep -v Name | awk '$6 >= 87 {printf $2 “\n” }'
-
2.4 sed命令
sed命令
sed 是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。
它不仅可以修改文件内容,还可以修改命令结果,支持管道符操作,这就是与vim最大的区别
sed [选项] ‘[动作]’ 文件名
选项:
- -n: 一般sed命令会把所有数据都输出到屏幕 , 如果加入此选择,则只会把经过sed命令处理的行输出到屏幕。
- -e: 允许对输入数据应用多条sed命令编辑
- -i: 用sed的修改结果直接修改读取数据的文件, 而不是由屏幕输出
动作:
- a : 追加,在当前行后添加一行或多行。添加多行时,除最后 一行外,每行末尾需要用“\”代表数据未完结。
- c : 行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结。
- i : 插入,在当期行前插入一行或多行。插入多行时,除最后 一行外,每行末尾需要用“\”代表数据未完结。
- d: 删除,删除指定的行。
- p:打印,输出指定的行。
- s:字串替换,用一个字符串替换另外一个字符串。格式为“行范 围s/旧字串/新字串/g”(和vim中的替换格式类似)。
例子:
sed ‘2p’ student.txt
查看文件的第二行会显示:
| ID | Name | PHP | Linux | MySQL | Average |
| ---- | ------ | ---- | ----- | ----- | ------- |
| 1 | Liming | 82 | 95 | 86 | 87.66 |
| 1 | Liming | 82 | 95 | 86 | 87.66 |
| 2 | Sc | 74 | 96 | 87 | 85.66 |
| 3 | Gao | 99 | 83 | 93 | 91.66 |
会发现多了一行,因为一般sed命令会把所有数据都输出到屏幕 ,只不过会先输出你想要的,这时候就需要-n配合
- sed -n ‘2p’ student.txt
输入-n后就没有多余的了
- sed ‘2,4d’ student.txt
删除第二行到第四行的数据,但不修改文件本身
- sed ‘2a hello’ student.txt
在第二行后追加hello
- sed ‘2i hello \ world’ student.txt
在第二行前插入两行数据
- sed '2c No such person‘ student.txt
数据替换
字符串替换
sed ‘s/旧字串/新字串/g’ 文件名
- sed ‘3s/74/99/g’ student.txt
在第三行中,把74换成99
- sed -i ‘3s/74/99/g’ student.txt
sed操作的数据直接写入文件
- sed -e ‘s/Liming//g ; s/Gao//g’ student.txt
同时把“Liming”和“Gao”替换为空
3. 字符处理命令
排序命令sort
sort [选项] 文件名
- -f:忽略大小写
- -n:以数值型进行排序,默认使用字符串型排序
- -r:反向排序
- -t:指定分隔符,默认是分隔符是制表符
- -k n[,m]: 按照指定的字段范围排序。从第n字段开始, m字段结束(默认到行尾)
例子:
- sort /etc/passwd
排序用户信息文件
- sort -r /etc/passwd
反向排序
- sort -t “:” -k 3,3 /etc/passwd
指定分隔符是“:”,用第三字段开头,第三字段结尾排序,就是只用第三字段排序,但是他不认识数字,会把数字当成字符串,认为3比11大 ,所以我需要加-n,进行数值排序
- sort -n -t “:” -k 3,3 /etc/passwd
统计命令wc
wc [选项] 文件名
- -l: 只统计行数
- -w: 只统计单词数
- -m: 只统计字符数
4. 条件判断
- 按照文件类型进行判断
测试选项 | 作用 |
---|---|
-b 文件 | 判断该文件是否存在,并且是否为 块设备文件(是块设备文件 为真) |
-c文件 | 判断该文件是否存在,并且是否为字符设备文件(是字符设备 文件为真) |
-d 文件 | 判断该文件是否存在,并且是否为目录文件(是目录为真) |
-e 文件 | 判断该文件是否存在(存在为真) |
-f 文件 | 判断该文件是否存在,并且是否为普通文件(是普通文件为真) |
-L 文件 | 判断该文件是否存在,并且是否为管道文件(是管道文件为真) |
-p 文件 | 判断该文件是否存在,并且是否为符号链接文件(是符号链接 文件为真) |
-s 文件 | 判断该文件是否存在,并且是否为非空(非空为真) |
-S 文件 | 判断该文件是否存在,并且是否为套接字文件(是套接字文件 为真) |
两种判断格式
上面的表结合一下命令来判断
test -e /root/install.log
[ -e /root/install.log ] 中括号两边必须有空格,只能为[ -e /root/install.log ] ,不能是[-e /root/install.log],在判断之后,使用echo $?来观察输出语句是否为真
[ -d /root ] && echo “yes” || echo "no" 第一个判断命令如果正确执行,则打印“yes”,否则打印“no”
- 按照文件权限进行判断
测试选项 | 作用 |
---|---|
-r 文件 | 判断该文件是否存在,并且是否该文件拥有读权限(有读 权限为真) |
-w文件 | 判断该文件是否存在,并且是否该文件拥有写权限(有写 权限为真) |
-x 文件 | 判断该文件是否存在,并且是否该文件拥有执行权限(有 执行权限为真) |
-u 文件 | 判断该文件是否存在,并且是否该文件拥有SUID权限(有 SUID权限为真) |
-g 文件 | 判断该文件是否存在,并且是否该文件拥有SGID权限(有 SGID权限为真) |
-k 文件 | 判断该文件是否存在,并且是否该文件拥有SBit权限(有 SBit权限为真) |
例子:
[ -w student.txt ] && echo “yes” || echo "no"
判断文件是拥有写权限的,不过系统不会区分,比如-w,只要所有者,所属组,其他人其中有一个有写权限,他就会返回yes,所以这个时候就需要我们自己写脚本
- 两个文件之间进行比较
测试选项 | 作用 |
---|---|
文件1 -nt 文件2 | 判断文件1的修改时间是否比文件2的新(如果新则为真) |
文件1 -ot 文件2 | 判断文件1的修改时间是否比文件2的旧(如果旧则为真) |
文件1 -ef 文件 | 判断文件1是否和文件2的Inode号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法 |
例子:
ln /root/student.txt /tmp/stu.txt
创建一个硬链接
[ /root/student.txt -ef /tmp/stu.txt ] && echo “yes” || echo “no” yes
用test测试
- 两个整数之间比较
测试选项 | 作用 |
---|---|
整数1 -eq 整数 2 | 判断整数1是否和整数2相等(相等为真) |
整数1 -ne 整数 2 | 判断整数1是否和整数2不相等(不相等位置) |
整数1 -gt 整数2 | 判断整数1是否大于整数2(大于为真) |
整数1 -lt 整数2 | 判断整数1是否小于整数2(小于位置) |
整数1 -ge 整数2 | 判断整数1是否大于等于整数2(大于等于为真) |
整数1 -le 整数2 | 判断整数1是否小于等于整数2(小于等于为真) |
例子:
- [ 23 -ge 22 ] && echo “yes” || echo “no” yes
判断23是否大于等于22
- [ 23 -le 22 ] && echo “yes” || echo “no” no
判断23是否小于等于22
- 字符串的判断
测试选项 | 作用 |
---|---|
-z 字符串 | 判断字符串是否为空(为空返回真) |
-n 字符串 | 判断字符串是否为非空(非空返回真) |
字串1 ==字串2 | 判断字符串1是否和字符串2相等(相等返回真) |
字串1 != 字串2 | 判断字符串1是否和字符串2不相等(不相等返回真) |
例子:
name=sc
给name变量赋值
[ -z “$name” ] && echo “yes” || echo “no” no
判断name变量是否为空,因为不为空,所以返回no
aa=11
bb=22
给变量aa和变量bb赋值
[ “$aa” == “$bb" ] && echo “yes” || echo "no"
判断两个变量的值是否相等,明显不相等 ,所以返回no
- 多重条件判断
测试选项 | 作用 |
---|---|
判断1 -a 判断2 | 逻辑与,判断1和判断2都成立,最终的结果才为真 |
判断1 -o 判断2 | 逻辑或,判断1和判断2有一个成立,最终的结果就为 真 |
!判断 | 逻辑非,使原始的判断式取反 |
例子:
aa=11
[ -n “$aa” -a “$aa” -gt 23 ] && echo “yes” || echo "no"
判断变量aa是否有值,同时判断变量aa的是否大于23
因为变量aa的值不大于23,所以虽然第一个判断值为真, 返回的结果也是假
aa=24
[ -n “$aa” -a “$aa” -gt 23 ] && echo “yes” || echo “no” yes
5. 流程控制
5.1 if语句
- 单分支if条件语句
if [ 条件判断式 ];then
程序
fi
123
或者
if [ 条件判断式 ]
then
程序
fi
1234
单分支条件语句需要注意几个点
- if语句使用fi结尾,和一般语言使用大括号结尾不同
- [ 条件判断式 ]就是使用test命令判断,所以中括号和条件判断式之间必须有空格
- then后面跟符合条件之后执行的程序,可以放在[]之后,用“;”分割。也可以换行写入,就不需要“;”了
例子:判断分区使用率
#!/bin/bash #统计根分区使用率
#Author: maqian (E-mail: 88888@qq.com)
rate=$(df -h | grep "/dev/sda3" | awk '{print $5}' | cut -d "%" - f1)
#把根分区使用率作为变量值赋予变量rate
if [ $rate -ge 80 ]
then
echo "Warning! /dev/sda3 is full!!"
fi
12345678
- 双分支if条件语句
if [ 条件判断式]
then
条件成立时,执行的程序
else
条件不成立时,执行的另一个程序
fi
例子1:备份mysql数据库
#!/bin/bash
#备份mysql数据库。
#Author: maqian (E-mail: 88888@qq.com)
ntpdate asia.pool.ntp.org &>/dev/null #同步系统时间
date=$(date +%y%m%d) #把当前系统时间按照“年月日”格式赋予变量date
size=$(du -sh /var/lib/mysql) #统计mysql数据库的大小,并把大小赋予size变量
if [ -d /tmp/dbbak ]
then
echo "Date : $date!" > /tmp/dbbak/dbinfo.txt
echo "Data size : $size" >> /tmp/dbbak/dbinfo.txt
cd /tmp/dbbak
tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>/dev/null
rm -rf /tmp/dbbak/dbinfo.txt
else
mkdir /tmp/dbbak
echo "Date : $date!" > /tmp/dbbak/dbinfo.txt
echo "Data size : $size" >> /tmp/dbbak/dbinfo.txt
cd /tmp/dbbak
tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>/dev/null
rm -rf /tmp/dbbak/dbinfo.txt
fi
例子2:判断apache是否启动
#!/bin/bash
#Author: maqian (E-mail: 88888@qq.com)
port=$(nmap -sT 47.95.5.171 | grep tcp | grep http | awk '{print $2}')
#使用nmap命令扫描服务器,并截取apache服务的状态,赋予变量port if [ "$port" == "open" ]
then
echo “$(date) httpd is ok!” >> /tmp/autostart-acc.log
else
/etc/rc.d/init.d/httpd start &>/dev/null
echo "$(date) restart httpd !!" >> /tmp/autostart-err.log
fi
nmap 远程扫描,检查服务是否启动
nmap -sT 扫描指定服务器上开启的TCP端口
- 多分支if条件语句
if [ 条件判断式1 ]
then
当条件判断式1成立时,执行程序1
elif [ 条件判断式2 ]
then
当条件判断式2成立时,执行程序2
...省略更多条件...
else
当所有条件都不成立时,最后执行此程序
fi
例子:
#!/bin/bash #判断用户输入的是什么文件
#Author: maqian (E-mail: 88888@qq.com)
read -p "Please input a filename: " file
#接收键盘的输入,并赋予变量file if [ -z "$file" ]
#判断file变量是否为空
then
echo "Error,please input a filename"
exit 1 #定义错误返回值1
elif [ ! -e "$file" ] #判断file的值是否存在
then
echo "Your input is not a file!"
exit 2 #定义错误返回值2
elif [ -f "$file" ] #判断file的值是否为普通文件
then
echo "$file is a regulare file!"
elif [ -d "$file" ] #判断file的值是否为目录文件
then
echo "$file is a directory!"
else
echo "$file is an other file!"
fi
5.2 case语句
多分支case条件语句
case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
...省略其他分支... *)
如果变量的值都不是以上的值,则执行此程序
;;
esac
用于选择列表,打印选择车票
例子:
#!/bin/bash #判断用户输入
#Author: maqian (E-mail: 88888@qq.com)
read -p "Please choose yes/no: " -t 30 cho
case $cho in
"yes")
echo "Your choose is yes!"
;;
"no")
echo "Your choose is no!"
;;
*)
echo "Your choose is error!"
;;
esac
5.3 for循环
- 语法一
for 变量 in 值1 值2 值3
do
程序
done
例子
#!/bin/bash
#Author: maqian (E-mail: 88888@qq.com)
#打印时间
for time in morning noon afternoon evening
do
echo “This time is $time!”
done
这种方法看起来很笨,需要把循环次数写入for,但是在系统管理的时候,当我们不确定循环次数的时候,比如解压缩一个文件里所有的压缩包,他会自动加入新的压缩包,这个时候我就需要用这种笨办法,这种后面加次数的也有一个好处,就是循环变量只要是由空格,或者回车,或者tab键隔开的,都可以算在内,所以才能和cat,ls等命令结合使用,cat命令执行之后显示的结果就是由回车隔开的,都可以算成是循环变量。在加入或者减少压缩包的时候,不需要修改脚本。
例子1:批量解压缩
#!/bin/bash
#Author: maqian (E-mail: 88888@qq.com)
#批量解压缩软件包
cd /lamp
ls *.tar.gz > ls.log #ls *.tar.gz 输出结果覆盖到ls.log文件
for i in $(cat ls.log)
do
tar -zxf $i $>/dev/null
done
rm -rf /lamp/ls.log
123456789101112
例子2:打印车票
#!/bin/bash
#Author: maqian (E-mail: 88888@qq.com)
#计算文件个数,并打印到屏幕
cd /root/sh
ls *.sh > ls.log
for i in $(cat ls.log)
do
echo $y
y=$(($y+1))
done
rm -rf ls.log
- 语法二
for ((初始值;循环控制调节;变量变化))
do
程序
done
例子:计算1加到100
#!/bin/bash
#Author: maqian (E-mail: 88888@qq.com)
#计算1加到100
s=0
for ((i=1;i<=100;i++))
do
s=$(($s+$i))
done
echo "The sum of 1+2+...+99+100 is $s!"
这种情况适用于知道循环次数
例子:批量创建用户
#!/bin/bash
#Author: maqian (E-mail: 88888@qq.com)
#批量添加新用户
read -p "Please input user name: " -t 30 name #输入用户名,等待时间30s
read -p "Please input the number of users: " -t 30 num #输入创建用户个数,等待时间30s
read -p "Please input the password of users: " -t 30 pass #输入用户密码,等待时间30s
if [ ! -z "$name" -a ! -z "$num" -a ! -z "$pass" ] #判断输入信息是否为空
then
y=$(echo $num | sed s/'^[0-9]*$'//g) #这里是判断输入的用户个数是否为数字,sed后也可以把^[0-9]*$换为's/[0-9]//g'
if [ -z "$y" ] #如果上一条语句输出不为空,就是输入的用户个数为数字,继续执行
then
for ((i=1;i<=$num;i++)) #开始循环
do
/usr/sbin/useradd "$name$i" &>/dev/null #建立用户
echo $pass | /usr/bin/passwd --stdin "$name$i" &>/dev/null #设置用户密码,与用户名相同
done
echo "Build seccees!"
fi
fi
如果输入的时候输错了需要按,ctrl+退格键
5.4 while循环与until循环
while循环:while循环是不定循环,也称作条件循环 。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和for的固定循环不太一样了。
while [ 条件判断式 ]
do
程序
done
1234
例子:从1加到100
#!/bin/bash
#Author: maqian (E-mail: 88888@qq.com)
#从1加到100
i=1
s=0
while [ $i -le 100 ] #如果变量i的值小于等于100,则执行循环
do
s=$(( $s+$i ))
i=$(( $i+1 ))
done
echo "The sum is: $s"
until循环
until循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
until [ 条件判断式 ]
do
程序
done
1234
例子:从1加到100
#!/bin/bash
#Author: maqian (E-mail: 88888@qq.com)
#从1加到100
i=1
s=0
until [ $i -gt 100 ] #循环直到变量i的值大于100,就停止循环
do
s=$(( $s+$i ))
i=$(( $i+1 ))
done
echo "The sum is: $s"