shell编程
1.Shell概述
Shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核
Shell还是一个功能相当强大的编程语言,易编写、易调试、灵活性强。
Linux提供的Shell解析器有:
2.Shell脚本入门
脚本以 #!/bin/bash 开头(指定解析器)
(1)创建一个Shell脚本:
(2)输入以下内容:
#!/bin/bash
echo "hello,world"
(3)脚本的常用执行方式:
第一种:采用bash或sh+脚本的相对路径或绝对路径(不用赋予脚本+x权限)
sh+脚本的相对路径
sh+脚本的绝对路径
bash+脚本的相对路径
bash+脚本的绝对路径
第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)
①首先赋予hello.sh脚本的+x权限:
②执行脚本
第三种:在脚本的路径前加上“.”或者source
3.变量
3.1系统预定义变量
常用系统变量:$HOME、 $PWD、 $SHELL、 $USER等
查看系统变量的值:
显示当前Shell中所有变量:set或者env
3.2自定义变量
1.基本语法
(1)定义变量:变量名=变量值,注意,=前后不能有空格
(2)撤销变量:unset 变量名
(3)声明静态变量:readonly 变量,注意,不能unset
2.定义变量规则
(1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写
(2)等号两侧不能有空格
(3)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。若要运算,需加两层括号 “$((运算式))” 或者使用中括号 " $[运算式]"
另一种运算方法:
(4)变量的值如果有空格,需要使用双引号或单引号括起来
目前,$my_var是一个局部环境变量,要把它变为全局环境变量,需要进行如下操作:
在hello.sh中添加环境变量:
#!/bin/bash
echo "hello,world"
echo $my_var
echo $new_var
3.3 特殊变量
$n
n为数字,$0代表该脚本名称, $1- $9代表第一到第九个参数,十以上的参数需要用大括号包含,如 ${10}
parameter.sh文件中内容为:
#!/bin/bash
echo '==================$n==================='
echo script name: $0
echo 1st parameter: $1
echo 2st parameter: $2
显示的结果为:
$#
获取所有输入参数个数,常用于循环判断参数的个数是否正确以及加强脚本的健壮性
文件中输入的内容:
#!/bin/bash
echo '==================$n==================='
echo script name: $0
echo 1st parameter: $1
echo 2st parameter: $2
echo '==================$#==================='
echo parameter numbers: $#
显示的结果:
$*、 $@
$:这个变量代表命令行中所有的参数, $*把所有的参数看成一个整体
$@:这个变量也代表命令行中所有的参数,不过 $@把每个参数区分对待
parameter_for_test.sh 文件中的内容:
#!/bin/bash
echo '===========$*============'
for para in "$*"
do
echo $para
done
echo '===========$@============'
for para in "$@"
do
echo $para
done
显示的结果:
$?
最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。
4.条件判断
基本语法:
test condition
[condition]
注:条件非空即为true,[frank]返回true,[ ]返回false
=两侧要空格
常用判断条件
(1)两个整数比较
选项 | 说明 |
---|---|
-eq | 等于(equal) |
-ne | 不等于(not equal) |
-lt | 小于(less than) |
-le | 小于等于(less equal) |
-gt | 大于(greater than) |
-ge | 大于等于(greater equal) |
(2)按照文件类型进行判断
选项 | 说明 |
---|---|
-e | 文件存在(existence) |
-f | 文件存在并且是一个常规的文件(file) |
-d | 文件存在并且是一个目录(directory) |
(3)多条件判断
符号 | 说明 |
---|---|
&& | 表示前一条命令执行成功时,才执行后一条命令 |
|| | 表示上一条命令执行失败后,才执行下一条命令 |
5.流程控制
5.1 if判断
5.1.1 单分支
基本语法1:
if [ 条件判断式 ];then
程序
fi
示例1:
示例2:
或者基本语法2:
if [ 条件判断式 ]
then
程序
fi
文件内容:
#!/bin/bash
if [ "$1"x = "xudoudou"x ]
then
echo "hello,xudoudou"
fi
显示结果:
5.1.2 多分支
基本语法:
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
示例1:文件内容:
#!/bin/bash
if [ "$1"x = "xudoudou"x ]
then
echo "hello,xudoudou"
fi
#
if [ $2 -lt 18 ]
then
echo "student"
elif [ $2 -lt 35 ]
then
echo "young people"
elif [ $2 -lt 60 ]
then
echo "adult"
else
echo "old people"
fi
显示结果:
5.2 case语句
基本语法:
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
...省略其他分支...
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
(1)case行为必须为单词 “in”,每一个模式匹配必须以右括号 “)” 结束
(2)双分号 “;;” 表示命令序列结束,相当于 JAVA 中的 break
(3)最后的 “*)” 表示默认模式,相当于 JAVA 中的 default
case_test.sh 文件中的内容:
#!/bin/bash
case $1 in
1)
echo "one"
;;
2)
echo "two"
;;
3)
echo "three"
;;
*)
echo "number else"
;;
esac
显示的结果:
5.3 for循环
1.基本语法1
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
文件中的内容:
#!/bin/bash
for (( i=1; i <= $1; i++ ))
do
sum=$[ $sum + $i ]
done
echo $sum
显示的结果:
2.基本语法2
for 变量 in 值1 值2 值3 ...
do
程序
done
示例1:
示例2:
5.4 while循环
基本语法:
while [ 条件判断式 ]
do
程序
done
while_test 文件的内容:
#!/bin/bash
a=1
while [ $a -le $1 ]
do
# sum=$[ $sum + $a ]
# a=$[ $a + 1 ]
let sum+=a
let a++
done
echo $sum
显示的结果:
6.read读取控制台输入
基本语法:
read (选项) (参数)
选项 | 说明 |
---|---|
-p | 指定读取值时的提示符 |
-t | 指定读取值时等待的时间(秒),如果 -t 不加表示一直等待 |
read_test.sh 文件中的内容为:
#!/bin/bash
read -t 10 -p "Please input your name:" name
echo "welcome,$name"
显示的结果为:
7.函数
7.1系统函数
7.1.1 basename
基本语法:
basename [string/pathname] [suffix]
basename命令会删掉所有的前缀包括最后一个(“/”)字符,然后将字符串显示出来
basename可以理解为取路径里的文件名称
suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉
示例1:
示例2:修改parameter.sh 中的内容
#!/bin/bash
echo '==================$n==================='
echo script name: $(basename $0 .sh)
echo 1st parameter: $1
echo 2st parameter: $2
echo '==================$#==================='
echo parameter numbers: $#
echo '==================$*==================='
echo $*
echo '==================$@==================='
echo $@
显示的结果:
7.1.2 dirname
基本语法:
dirname 文件绝对路径
从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)
dirname 可以理解为取文件路径的绝对路径名称
示例1:
示例2:
parameter.sh 文件内容可以修改为:
#!/bin/bash
echo '==================$n==================='
echo script name: $(basename $0 .sh)
echo script path: $(cd $(dirname $0); pwd)
echo 1st parameter: $1
echo 2st parameter: $2
echo '==================$#==================='
echo parameter numbers: $#
echo '==================$*==================='
echo $*
echo '==================$@==================='
echo $@
显示的结果为:
7.2自定义函数
基本语法:
[function] funname[()]
{
Action;
[return int;]
}
示例:计算输入两个整数之和
#!/bin/bash
function add(){
s=$[$1 + $2]
echo "sum: "$s
}
read -p "Please input NO.one int: " a
read -p "Please input NO.two int: " b
add $a $b
显示结果:
8.综合案例——归档文件
需求:实现一个每天对指定目录归档备份的脚本,输入一个目录名称(末尾不带/),将目录下所有文件按天归档保存,并将归档日期附加在归档文件名上,放在/home/frank/archive下。
这里用到了归档命令:tar
后面加上 -c 选项表示归档,加上 -z 选项表示同时进行压缩,得到的文件后缀名为 .tar.gz
脚本实现:
#!/bin/bash
#首先判断输入参数个数是否为1
if [ $# -ne 1 ]
then
echo "参数个数错误!应该输入一个参数,作为归档目录名"
exit
fi
#从参数中获取目录名称
if [ -d $1 ]
then
echo
else
echo
echo "目录不存在!"
echo
exit
fi
DIR_NAME=$(basename $1)
DIR_PATH=$(cd $(dirname $1); pwd)
#获取当前日期
DATE=$(date +%y%m%d)
#定义生成的归档文件名称
FILE=archive_${DIR_NAME}_$DATE.tar.gz
DEST=/home/frank/archive/$FILE
#开始归档目录文件
echo "开始归档..."
echo
tar -czf $DEST $DIR_PATH/$DIR_NAME
if [ $? -eq 0 ]
then
echo
echo "归档成功!"
echo "归档文件为:$DEST"
echo
else
echo "归档出现问题!"
echo
fi
exit
执行该脚本:
9.文本处理工具
9.1 cut
cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut命令从文件的每一行剪切字节、字符和字段,并将这些字节、字符和字段输出。
cut [选项参数] filename
选项参数 | 功能 |
---|---|
-f | 列号,提取第几列 |
-d | 分隔符,按照指定分隔符分割列,默认是制表符“\t” |
-c | 字符进行切割后加n 表示取第几列 比如 -c 1 |
9.2 awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理
awk [选项参数] '/pattern1/{action1} /pattern2/{action2}...' filename
pattern:表示awk在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
选项参数 | 功能 |
---|---|
-F | 指定输入文件分隔符 |
-v | 赋值一个用户定义变量 |
awk的内置变量
变量 | 说明 |
---|---|
FILENAME | 文件名 |
NR | 已读的记录数(行号) |
NF | 浏览记录的域的个数(切割后,列的个数) |
示例1:统计passwd文件名,每行的行号,每列的列数
示例2:查询ifconfig命令输出结果中的空行所在的行数
笔记来源于课程:尚硅谷Linux课程