shell
什么是shell
shell是一个用c语言编写的程序,它是用户使用linux的桥梁。shell既是一种命令语言,又是一种程序设局语言。
shell是一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
shell属于内置的脚本,程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理活动)语法简单,代码写起来轻松,简单易学
shell的分类
$ cat /etc/shells
/bin/sh
/bin/bash 重点
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
/usr/bin/tmux
编写规范
#!/bin/bash [指定告知系统当前这个脚本要使用shell解释器]
shell 相关命令
文件命名规范
文件名.sh .sh 是linux下bash shell的默认前缀
输入输出重定向
输入重定向: 是指不使用系统提供的标准输入端口,而是使用指定的文件作为输入设备(重定向简单理解就是使用" < ”符来修改标准输入设备)
类型 | 符号(语法) | 功能 |
---|---|---|
标准输入 | 命令<文件1 | 命令把文件1的内容作为标准输入设备 |
标识符限定输入 | 命令<<标识符 | 命令把标准输入中读入内容,直到遇到“标识符”分解符为止 |
输入输出重定向(同时使用) | 命令< 文件1 >文件2 | 命令把文件1的内容作为标准输入,把文件2作为标准输出。 |
输出重定向
把要输出的文件信息写到一个文件中去,而不是将要输出的文件信息输出到控制台
& 表示全部文件,文件不管对错;1 表示标准输出文件,2表示标准错误输出
类型 | 符号 | 作用 |
---|---|---|
标住输出重定向 | 命令 > 文件 | 以覆盖方式,把命令的正确输出内容输出到指定的文件或设备当中 |
标住输出重定向 | 命令 >> 文件 | 以追加方式,把命令的正确输出内容输出到指定的文件或设备当中 |
标准错误输出重定向 | 错误命令2 > 文件 | 以覆盖方式,把命令的错误输出输出到指定的文件或设备当中 |
标准错误输出重定向 | 错误命令2 >> 文件 | 以追加方式,把命令的错误输出输出到指定的文件或设备当中 |
正确输出和错误输出同时保存 | 命令 > 文件 2>&1 | 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 >> 文件 2>&1 | 以追加的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 &> 文件 | 以覆盖的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 &>> 文件 | 以追加的方式,把正确输出和错误输出都保存到同一个文件当中。 |
正确输出和错误输出同时保存 | 命令 >> 文件1 2>>文件2 | 把正确的输出追加到文件1中,把错误的输出追加到文件2中。 |
/dev/null文件 |
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到“/dev/null”中
[root@localhost ~]$ command > dev/null
多命令顺序执行
多命令执行行符 | 格式 | 作用 |
---|---|---|
; | 命令1 ;命令2 | 多个命令顺序执行,命令之间没有任何逻辑联系 |
&& | 命令1 && 命令2 | 当命令1正确执行(? = 0 ) , 则 命 令 2 才 会 执 行 当 命 令 1 执 行 不 正 确 ( ?=0),则命令2才会执行 当命令1执行不正确(?=0),则命令2才会执行当命令1执行不正确(?≠0),则命令2不会执行 |
ll | 命令1 || 命令2 | 当命令1执行不正确(? ≠ 0 ) , 则 命 令 2 才 会 执 行 当 命 令 1 正 确 执 行 ( ?≠0),则命令2才会执行当命令1正确执行(? \ =0),则命令2才会执行当命令1正确执行(?=0),则命令2不会执行 |
shell脚本执行
[root@localhost ~]$ vim test.sh
#!/bin/bash
echo "hello world"
两种方式执行shell脚本
-
给文件添加执行权限
chmod -u+x test.sh ./test.sh
-
通过bash调用执行脚本
shell 变量
变量命名规则
- 只能使用英文字符,数字和下划线,不能以数字开头
- 等号左右两侧不能有空格,可以使用下划线“_”,变量的值如果有空格,需要使用单引号或双引号包括。如:“test=“hello world!””。其中双引号括起来的内容“$”,“(”和反引号都拥有特殊含义,而单引号括起来的内容都是普通字符。
- 不能使用标点符号,不能使用bash里的关键字
- 环境变量建议大写,便于区分
- 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含"$变量名"或用${变量名}包含变量名。
单双引号的问题
- 双引号能够识别变量,双引号能够实现转义(类似于 “*”)
- 单引是不能识别变量,只会原样输出,单引号是不能转义的
shell中特殊符号
符号 | 作用 |
---|---|
' ' | 单引号。在单引号中所有的特殊符号,如“$”和”(反引号)都没有特殊含义。单引号括起来的都是普通字符,会原样输出 单引号内的内容会原样输出 |
" " | 双引号。在双引号中特殊符号都没有特殊含义,但是“$”,"`"(esc键下面)和“\”是例外,拥有“调用变量的值”、“引用命令”和“转义符”的特殊含义。 |
`` | 反引号。反引号括起来的内容是系统命令,在Bash中会先执行它。和( ) 作 用 一 样 , 不 过 推 荐 使 用 ()作用一样,不过推荐使用()作用一样,不过推荐使用(),因为反引号非常容易看错。 |
$( ) | 反引号作用一样,用量引用系统指令(推荐使用) |
() | 用于一串命令执行时,()中的命令会在子Shell中运行 |
{} | 用于一串命令执行时,{ }中的命令会在当前Shell中执行。也可以用于变量变形与替换。 |
[ ] | 用于变量的测试 |
# | 在shell脚本中,#开头的行代表注释 |
$ | 用于调用变量的值,如需要调用变量name的值时,需要用$name的方式得到变量的值。 |
\ | 转义符,跟在\之后的特殊符号将失去特殊含义,变为普通字符。如$将输出“$”符号,而不当做是变量引用。 |
变量分类
-
用户自定义变量: 最常见的变量,由用户定义的变量名和变量值
-
环境变量:
这种变量中主要保存的是和系统操作环境相关的数据,比如当前登录用户,用户的家目录,命令的提示符等。不是太好理解吧,那么大家还记得在Windows中,同一台电脑可以有多个用户登录,而且每个用户都可以定义自己的桌面样式和分辨率,这些其实就是Windows的操作环境,可以当做是Windows的环境变量来理解。环境变量的变量名可以自由定义,但是一般对系统起作用的环境变量的变量名是系统预先设定好的。
-
位置参数变量:
这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。
-
预定义变量:
是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
变量查看
[root@localhost ~]$ set [选项]
选项:
-u:如果设定此选项,调用未声明变量时会报错(默认无任何提示)
-x:如果设定此选项,在命令执行之前,会把命令先输出一次
+<参数> :取消某个set曾启动的参数。
[root@localhost ~]$ set
BASH=/bin/bash
…省略部分输出…
name='shen chao'
#直接使用set 命令,会查询系统中所有的变量,包含用户自定义变量和环境变量
[root@localhost ~]$ set -u
[root@localhost ~]$ echo $file
-bash: file: unbound variable
#当设置了-u选项后,如果调用没有设定的变量会有报错。默认是没有任何输出的。
[root@localhost ~]$ set -x
[root@localhost ~]$ ls
+ls --color=auto
anaconda-ks.cfginstall.loginstall.log.syslog sh tdir testtestfile
#如果设定了-x选项,会在每个命令执行之前,先把命令输出一次
[root@localhost ~]$ set +x
#取消启动的x参数
env命令和set命令的区别
- set命令可以查看所有变量
- env命令只能查看环境变量
变量删除
[root@localhost ~]$ unset 变量名
位置参数变量
位置参数变量 | 作用 |
---|---|
$n | n为数字,$0表示当前 Shell 脚本程序的名称,$1-9 代 表 第 一 到 第 九 个 参 数 , 十 以 上 的 参 数 需 要 用 大 括 号 包 含 , 如 9代表第一到第九个参数,十以上的参数需要用大括号包含,如9代表第一到第九个参数,十以上的参数需要用大括号包含,如{10} |
$* | 这个变量代表命令行中所有的参数,$把所有的参数看成一个整体 |
$@ | 这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待 |
$# | 这个变量代表命令行中所有参数的个数 |
预定义变量
预定义变量 | 作用 |
---|---|
$? | 最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。 |
$$ | 当前进程的进程号(PID) |
$! | 后台运行的最后一个进程的进程号(PID) |
接受键盘输入
[root@localhost ~]$ read [选项][变量名]
选项:
-a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符。
-p: “提示信息”:在等待read输入时,输出提示信息
-t: 秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间
-n: 数字:read命令只接受指定的字符数,就会执行
-s: 隐藏输入的数据,适用于机密信息的输入
-d: 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志。
-e: 在输入的时候可以使用命令补全功能。
变量名:
变量名可以自定义,如果不指定变量名,会把输入保存入默认变量REPLY.
如果只提供了一个变量名,则整个输入行赋予该变量.
如果提供了一个以上的变量名,则输入行分为若干字,一个接一个地赋予各个变量,而命令行上的最后一个变量取得剩余的所有字
[root@localhost sh]$ vi read.sh
#!/bin/bash
read -t 30 -p "Please input your name: " name
#提示“请输入姓名”并等待30 秒,把用户的输入保存入变量name 中
echo "Name is $name"
#看看变量“$name”中是否保存了你的输入
read -s -t 30 -p "Please enter your age: " age
#提示“请输入年龄”并等待30秒,把用户的输入保存入变量age中
#年龄是隐私,所以我们用“-s”选项隐藏输入
echo -e "\n"
#调整输出格式,如果不输出换行,一会的年龄输出不会换行
echo "Age is $age"
read -n 1 -t 30 -p "Please select your gender[M/F]:" gender
#提示“请选择性别”并等待30秒,把用户的输入保存入变量gender
#使用“-n1”选项只接收一个输入字符就会执行(都不用输入回车)
echo -e "\n"
echo "Sex is $gender"
运算符
算数运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):
[root@localhost ~]$ vi computer.sh
#!/bin/bash
val=`expr 2 + 2`
echo "两数之和为 : $val"
#注意
#表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
#完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20
运算符 | 说明 | 举例 |
---|---|---|
+ | expr $a + $b 结果为 30。 |
|
- | expr $a - $b 结果为 -10。 |
|
* | expr $a \* $b 结果为 200。 |
|
/ | expr $b / $a 结果为 2。 |
|
% | expr $b % $a 结果为 0。 |
|
= | 赋值 | a=$b 将把变量 b 的值赋给 a。 |
== | 相等 | [ $a == $b ] 返回 false(假)。 |
注意:表达式要放在方括号之间,并且要有空格,必须写成[ $a == $b ]
[root@localhost ~]$ vi computers.sh
#!/bin/bash
a=10
b=20
echo ' '
echo 'a+b= ' `expr $a + $b`
echo 'a-b= ' `expr $a - $b`
echo 'a*b= ' `expr $a \* $b`
echo 'a/b= ' `expr $a / $b`
echo 'a%b= ' `expr $a % $b`
#判断是否相等
if [ $a == $b ]
then
echo 'a等于b'
else
echo 'a不等于b'
fi
关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字
下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 单词 | 说明 | 举例 |
---|---|---|---|
-eq | equal | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 false。 |
-ne | not equal | 检测两个数是否相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | great than | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | less than | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | great than or equal | 检测左边的数是否大于等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | less than or equal | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
案例:判断当前输入的用户是否存在。如果存在则提示“用户存在”否则提示“用户不存在”。
**如果要在shell脚本使用linux命令,可以使用$()
包裹命令
例如:disk_size=$(df -h | awk ‘NR==2 {print $5}’)
[root@localhost ~]$ vim demo.sh
#!/bin/bash
#接受用户的输入
read -p '请输入需要查询的用户名:' username
#获取指定用户名在passwd文件中出现的次数
count=$(cat /etc/passwd | grep $username | wc -l)
#count=`cat /etc/passwd | grep $username | wc -l`
#判断出现的次数,如果次数=0则用户不存在,反之存在
if [ $count == 0 ]
then
echo '用户不存在'
else
echo '用户存在'
fi
逻辑运算符
下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或(或者)运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与(并且)运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
或运算:一个为真即为真,全部为假才是假
与运算:一个为假即为假,全部为真才是真
字符串运算
下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否为0,不为0返回 true。 | [ -n $a ] 返回 true。 |
str | 检测字符串是否为空,不为空返回 true。 | [ $a ] 返回 true。 |
文件测试运算符(重点)
文件测试运算符用于检测 Unix/Linux 文件的各种属性。
操作符 | 说明 | 举例 |
---|---|---|
-b file | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
-c file | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] 返回 false。 |
-d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false。 |
-f file | 检测文件是否是普通文件 (既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 |
-g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 |
-p file | 检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 |
-u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 |
-r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空 (文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 |
注意:权限几个判断,如果只有一个部分符合,则认为是有权限的。
流程控制
if条件判断
单分支if条件
if [ 条件判断式 ]
then
程序
fi
案例:统计根分区使用率
[root@localhost ~]$ vi sh/if1.sh
#!/bin/bash
#统计根分区使用率
rate=$(df -h | grep "/dev/sda2" | awk '{print $5}’| cut -d "%"-f1)
#把根分区使用率作为变量值赋予变量rate
if [ $rate -ge 80 ]
#判断rate的值如果大于等于80,则执行then程序
then
echo "Warning!/dev/sda3 is fu11!!"
#打印警告信息。在实际工作中,也可以向管理员发送邮件。
fi
[root@localhost ~]$ vi sh/if1.sh
#!/bin/bash
#统计根分区使用率
rate=$(df -h | grep "/dev/sda2" | awk '{print $5}’| cut -d "%"-f1)
#把根分区使用率作为变量值赋予变量rate
if [ $rate -ge 80 ]
#判断rate的值如果大于等于80,则执行then程序
then
echo "Warning!/dev/sda3 is fu11!!"
#打印警告信息。在实际工作中,也可以向管理员发送邮件。
fi
案例:创建目录
[root@localhost ~]$ vi sh/add_dir.sh
#!/bin/bash
#创建目录,判断是否存在,存在就结束,反之创建
echo "当前脚本名称为$0"
DIR="/media/cdrom"
if [ ! -e $DIR ]
then
mkdir -p $DIR
fi
echo "$DIR 创建成功"
双分支if条件语句
if [ 条件判断式 ]
then
条件成立时,执行的程序
else
条件不成立时,执行的另一个程序
fi
多分支if条件语句
if [ 条件判断式1 ]
then
当条件判断式1成立时,执行程序1
elif [ 条件判断式2 ]
then
当条件判断式2成立时,执行程序2
…省略更多条件…
else
当所有条件都不成立时,最后执行此程序
fi
多分支case条件语句
case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
::
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
这个语句需要注意以下内容:
- case语句,会取出变量中的值,然后与语句体中的值逐一比较。如果数值符合,则执行对应的程序,如果数值不符,则依次比较下一个值。如果所有的值都不符合,则执行 “*) ” ( *代表所有其他值)中的程序。
- case语句以“case”开头,以“esac”结尾。
[root@localhost ~]$ vi sh/if-case.sh
#!/bin/bash
read -p "请输入一个字符,并按Enter确认:" KEY
case "$KEY" in
[a-z]|[A-Z])
echo "您输入的是字母"
;;
[0-9])
echo "您输入的是数字"
;;
*)
echo "您输入的是其他字符"
;;
esac
for循环
for循环是固定循环,也就是在循环时已经知道需要进行几次的循环,有时也把for循环称为计数循环。for的语法有如下两种:
语法一:
for 变量 in 值1 值2 值3 …(可以是一个文件等)
do
程序
done
这种语法中for循环的次数,取决于in后面值的个数(空格分隔),有几个值就循环几次,并且每次循环都把值赋予变量。
也就是说,假设in后面有三个值,for会循环三次,第一次循环会把值1赋予变量,第二次循环会把值2赋予变量,以此类推。
语法二:
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
语法二中需要注意:
初始值:在循环开始时,需要给某个变量赋予初始值,如i=1;
循环控制条件:用于指定变量循环的次数,如i<=100,则只要i的值小于等于100,循环就会继续;
变量变化:每次循环之后,变量该如何变化,如i=i+1。代表每次循环之后,变量i的值都加1。
while循环
对while循环来讲,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。
语法:
while [ 条件判断式 ]
do
程序
done
until循环
和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
until [ 条件判断式 ]
do
程序
done
函数
function 函数名() {
}
案例:接受用户输入的数字,然后从1加到这个数字
[root@localhost ~]$ vi sh/function.sh
#!/bin/bash
#接收用户输入的数字,然后从1加到这个数字
function sum () {
#定义函数sum
s=0
for (( i=0; i<=$num;i=i+1 ))
#循环直到i大于$1为止。$1是函数sum 的第一个参数
#在函数中也可以使用位置参数变量,不过这里的$1指的是函数的第一个参数
do
s=$(( $i+$s ))
done
echo "The sum of 1+2+3...+$1 is :$s"
#输出1加到$1的和
}
read -p "Please input a number: " -t 30 num
#接收用户输入的数字,并把值赋予变量num
y=$(echo $num | sed 's/[0-9]//g')
#把变量num的值替换为空,并赋予变量y
if [ -z "$y"]
#判断变量y是否为空,以确定变量num中是否为数字
then
sum $num
#调用sum函数,并把变量num的值作为第一个参数传递给sum函数
else
echo "Error!! Please input a number!"
#如果变量num 的值不是数字,则输出报错信息
fi
特殊流程控制语句
exit语句
系统是有exit命令的,用于退出当前用户的登录状态。可是在Shell脚本中,exit语句是用来退出当前脚本的。也就是说,在Shell脚本中,只要碰到了exit语句,后续的程序就不再执行,而直接退出脚本。
exit的语法如下:
exit [返回值]
如果exit命令之后定义了返回值,那么这个脚本执行之后的返回值就是我们自己定义的返回值。可以通过查询$?这个变量,来查看返回值。如果exit之后没有定义返回值,脚本执行之后的返回值是执行exit 语句之前,最后执行的一条命令的返回值。写一个exit 的例子:
[root@localhost ~]$ vi sh/exit.sh
#!/bin/bash
#演示exit的作用
read -p "Please input a number: " -t 30 num
#接收用户的输入,并把输入赋予变量num
y=$ (echo $num | sed 's/[0-9]//g')
#如果变量num 的值是数字,则把num的值替换为空,否则不替换
#把替换之后的值赋予变量y
[ -n "$y" ] && echo "Error! Please input a number!" && exit 18
#判断变量y的值如果不为空,输出报错信息,退出脚本,退出返回值为18
echo "The number is: $num"
#如果没有退出加班,则打印变量num中的数字
break语句
当程序执行到break语句时,会结束整个当前循环。而continue 语句也是结束循环的语句,不过continue 语句单次当前循环,而下次循环会继续。
[root@localhost ~]$ vi sh/break.sh
#!/bin/bash
#演示break 跳出循环
for (( i=1;i<=10; i=i+1 ))
#循环十次
do
if ["$i" -eq 4 ]
#如果变量i的值等于4
then
break
#退出整个循环
fi
echo $i
#输出变量i的值
done
continue语句
continue也是结束流程控制的语句。如果在循环中,continue语句只会结束单次当前循环。
[root@localhost ~]$ vi sh/break.sh
#!/bin/bash
#演示continue
for (( i=1;i<=10;i=i+1 ))
#循环十次
do
if ["$i" -eq 4 ]
#如果变量i的值等于4
then
continue
#退出换成continue
fi
echo $i
#输出变量i的值
done
字符截取、替换和处理命令
正则表达式
元字符 | 描述 | 示例 |
---|---|---|
\ | 转义符,将特殊符号进行转义,忽略其特殊意义 | a.b 匹配 a.b,但不能匹配 ajb,. 被转义为特殊意义 |
^ | 匹配行首,awk中,^则只是匹配字符串的开始 | ^tux 匹配以tux开头的行 |
$ | 匹配行尾,awk中,$则只是匹配字符串的结尾 | tux$ 匹配以tux结尾的行 |
. | 匹配除换行符\n之外的任意单个字符 | ab. 匹配abc或abd,不可匹配 abcde,只能匹配单个字符 |
[] | 匹配包含在符号[]之中的任意一个字符 | coo[lk] 可以匹配 cook 或 cool |
[^] | 匹配[^]符号之外的任意一个字符 | 123[^45] 不可可以匹配 1234 或 1235,1236,1237都可以 |
[-] | 匹配[]中指定范围内的任意一个字符,要与起始端 | [0-9]可以匹配 1,2或3等等中任意一个数字 |
? | 匹配之前前面的项1次或者0次 | colou?r 可以匹配color或者colour,不能匹配colouur |
+ | 匹配之前前面的项1次或者多次 | sa-6+ 匹配sa-6,sa-666,不能匹配sa- |
* | 匹配之前前面的项0次或者多次 | co*l 匹配cl,col,cool,cooool等 |
匹配表达式为空,创建一 个用于匹配的子串 | ma{tri}? 匹配max或matrix | |
匹配之前前面的项n次,n是可以为0的正整数 | [0-9]{3} 匹配任意一个三位数,可以为 910-9 | |
之前的项至少需要匹配n次 | [0-9]{2,} 匹配任意一个两位数或更多位数不必支持{n,} | |
指定之前前面的至少匹配n次,最多匹配m次,n<=m | [0-9]{2,5} 匹配从两位数到五位数之间的任意一个数字 | |
| | 交替匹配|两边的任意一项 | ab|cd 匹配abc或abd |
字符串截取,替换命令
cut列提取命令
[root@localhost ~]$ cut [选项] 文件名
选项:
-f 列号: 提取第几列
-d 分隔符: 按照指定分隔符分割列
-n 取消分割多字节字符
-c 字符范围: 不依赖分隔符来区分列,而是通过字符范围(行首为0)来进行字段提取。“n-”表示从第n个字符到行尾;“n-m”从第n个字符到第m个字符;“一m”表示从第1个字符到第m个字符。
--complement 补足被选择的字节、字符或字段
--out-delimiter 指定输出内容是的字段分割符
cut命令的默认分隔符是制表符,也就是“tab”键,不过对空格符可是支持的不怎么好啊。我们先建立一个测试文件,然后看看cut命令的作用吧:
[root@localhost ~]$ vi student.txt
id name gender mark
1 liming m 86
2 sc m 67
3 tg n 90
[root@localhost ~]$ cut -f 2 student.txt
#提取第二列内容
# 那如果想要提取多列呢?只要列号直接用“,”分开,命令如下:
[root@localhost ~]$ cut -f 2,3 student.txt
cut可以按照字符进行提取,需要注意“8-”代表的是提取所有行的第十个字符开始到行尾,而“10-20”代表提取所有行的第十个字符到第二十个字符,而“-8”代表提取所有行从行首到第八个字符:
[root@localhost ~]$ cut -c 8- student.txt
#提取第八个字符开始到行尾,好像很乱啊,那是因为每行的字符个数不相等啊
[root@localhost ~]$ cut -d ":" -f 1,3 /etc/passwd
#以“:”作为分隔符,提取/etc/passwd_文件的第一列和第三列
如果我想用cut命令截取df命令的第一列和第三列,就会出现这样的情况:
[root@localhost~]$ df -h | cut -d " " -f 1,3
Filesystem
/dev/sda2
tmpfs
/dev/sda1
awk编程
awk是一种处理文本文件的语言,是一个强大的文本分析工具
printf格式化输出
[root@localhost ~]$ printf ‘输出类型输出格式’ 输出内容
输出类型:
%c: ASCII字符.显示相对应参数的第一个字符
%-ns: 输出字符串,减号“-”表示左对齐(默认右对齐),n是数字指代输出几个字符,几个参数就写几个%-ns
%-ni: 输出整数,n是数字指代输出几个数字
%f: 输出小数点右边的位数
%m.nf: 输出浮点数,m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表共输出8位数,其中2位是小数,6位是整数。
输出格式:
\a: 输出警告声音
\b: 输出退格键,也就是Backspace键
\f: 清除屏幕
\n: 换行
\r: 回车,也就是Enter键
\t: 水平输出退格键,也就是Tab 键
\v: 垂直输出退格键,也就是Tab 键
为了演示printf命令,我们需要修改下刚刚cut命令使用的student.txt,文件内容如下:
[root@localhost ~]$ vi student.txt
ID Name php Linux MySQL Average
1 AAA 66 66 66 66
2 BBB 77 77 77 77
3 CCC 88 88 88 88
#printf格式输出文件
[root@localhost ~]$ printf '%s\t %s\t %s\t %s\t %s\t %s\t \n’ $(cat student.txt)
#%s分别对应后面的参数,6列就写6个
ID Name php Linux MySQL Average
1 AAA 66 66 66 66
2 BBB 77 77 77 77
3 CCC 88 88 88 88
如果不想把成绩当成字符串输出,而是按照整型和浮点型输出,则要这样:
[root@localhost ~]$ printf '%i\t %s\t %i\t %i\t %i\t %8.2f\t \n’ \ $(cat student.txt | grep -v Name)
awk基本使用
[root@localhost ~]$ awk‘条件1{动作1} 条件2{动作2}…’ 文件名
条件(Pattern):
一般使用关系表达式作为条件。这些关系表达式非常多,例如:
x > 10 判断变量x是否大于10
x == y 判断变量x是否等于变量y
A ~ B 判断字符串A中是否包含能匹配B表达式的子字符串
A !~ B 判断字符串A中是否不包含能匹配B表达式的子字符串
动作(Action) :
格式化输出
流程控制语句
常用参数:
-F 指定输入时用到的字段分隔符
-v 自定义变量
-f 从脚本中读取awk命令
-m 对val值设置内在限制