java开发——shell编程
- shell是什么东西?
- java程序员为什么要学习Shell?
- Shell的解析器
- 第一个Shell脚本
- Shell中的变量
- Shell的运算符
- Shell的条件判断
- Shell的if语句
- Shell的case语句
- Shell的for语句
- Shell的while语句
- Shell控制台输入
- Shell的系统函数
- Shell自定义函数
- Shell工具——Cut
- Shell工具——Sed
- Shell工具——Awk
- Shell工具——Sort
- Shell面试题
shell是什么东西?
Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(command interpreter,命令解析器)。它类似于DOS下的COMMAND.COM和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。
Shell还是一个功能相当强大的编程语言,易编写、易调试、灵活性强的特点
简单来说,Shell脚本给用户操作内核提供了接口,同时也可以对命令赋予了逻辑,什么时候执行什么命令都可以有编程人员进行设计
java程序员为什么要学习Shell?
1、看懂运维人员编写的Shell程序
Shell脚本相当于对底层命令的一个封装,在服务上线/维护的时候,运维人员一般会编写Shell脚本批量执行命令来管理服务。java程序员需要和运维人员沟通,能看懂Shell程序是最基本的前提
2、偶尔会编写一些简单的Shell程序来方便开发
对于一些复杂的过程,程序员可以使用简单的shell脚本使其变得简单起来。在开发过程中,通常需要使用到mysql、nacos、redis、rabbitMQ等等第三方工具,如果逐个启动/关闭,那就太麻烦了,此时就可以写个Shell脚本一键启动/关闭服务。另外地还有其它许多好用的Shell可以简便我们的开发
Shell的解析器
查看Shell的解析器命令:cat /etc/shells
可以看到,Shell语言的解析器有sh、bash等
查看目录详情:cll /bin/ | grep bash
实际上,sh是bash的软链接,就是使用sh解析器的时候实际使用的是bash解析器
第一个Shell脚本
1、编写脚本
创建my_sh目录:mkdir -p /home/my_sh/
创建并编写一个hello.sh脚本:vim /home/my_sh/hello.sh
输入以下内容:
#!/bin/bash
echo "hello world!"
默认各位都会linux基础了嗷,如果不会操作建议先学习linux基础
# 是注释的意思
#! 是指定解析器的意思,这里需要区分
echo 是相当于print,打印的意思
整个程序就是打印 helloworld!这一句话的意思
2、运行脚本
用绝对路径
命令:sh /home/my_sh/hello.sh
命令:bash /home/my_sh/hello.sh
命令:/home/my_sh/hello.sh
直接使用/home/my_sh/hello.sh发现权限不够,那是因为该文件没有可执行的权限,可以通过chmod分配权限解决
分配权限 chmod 777 /home/my_sh/hello.sh
再次执行:
用相对路径
需要先进入到/home/my_sh目录下:cd /home/my_sh/
命令:sh hello.sh
命令:bash hello.sh
命令:./hello.sh
./代表当前路径,使用相对路径时,需要使用./hello.sh,而不可以直接使用hello.sh
Shell中的变量
1、系统环境变量
在系统环境配置文件/etc/profile文件或/etc/profile.d/下的所有xx.sh文件中配置的环境变量,可以以$xxx的方式直接获取
例如:
echo $HOME
echo $USER
echo $SHELL
echo $JAVA_HOME
JAVA_HOME是我自己配置的环境变量
2、用户自定义变量
自定义变量可直接以=赋值,以$xxx的方式获取值
例如:A=1
打印:echo $A
注意: 等号两边不允许出现空格!A = 1、A= 1、A =1这些形式都是不可以的,是错误的
如果值存在特殊字符!&$、空格等特殊字符时,需要用单引号括起来
A=!&$ ggg
echo $A
A=‘!&$ ggg’
A='!&$ ggg'
echo $A
注意: 上面的单引号需要改为英文的,因为编码原因,请复制代码块里的代码
3、特殊变量
(1)$n: n为数字,$0代表脚本名称,$1-$9代表第一到第九个参数,十以上的参数需要用大括号包含,如${10},实则所有参数获取的方式都是${n},只是0-9的被简化为了$n而已
创建param脚本:vim /home/my_sh/param.sh
输入以下信息:
#!/bin/bash
echo "$0 $1 $2 ${3} ${4}"
执行脚本:sh /home/my_sh/param.sh
执行脚本:sh /home/my_sh/param.sh 参数1 参数2 参数3 参数4 参数5
可以发现,前面脚本名和前面4个参数都成功接收了
(2)$#: 获取所有输入参数的个数,参用于循环
编辑param脚本:vim /home/my_sh/param.sh
输入以下信息:
#!/bin/bash
echo "$0 $1 $2 ${3} ${4}"
echo $#
执行脚本:sh /home/my_sh/param.sh
执行脚本:sh /home/my_sh/param.sh 参数1 参数2 参数3 参数4 参数5
(3)$*、$@
$*: 代表命令行中所有参数,$*把所有的参数看出一个整体
$@: 代表命令行中所有参数,$@把每个参数区分看待
编辑param脚本:vim /home/my_sh/param.sh
输入以下信息:
#!/bin/bash
echo "$0 $1 $2 ${3} ${4}"
echo $#
echo $*
echo $@
执行脚本:sh /home/my_sh/param.sh
执行脚本:sh /home/my_sh/param.sh 参数1 参数2 参数3 参数4 参数5
这里是看不出区别的,但是在循环里就容易看出来的
编辑param脚本:vim /home/my_sh/param.sh
输入以下信息:
#!/bin/bash
echo "$0 $1 $2 ${3} ${4}"
echo $#
for parm in "$*"
do
echo $parm
done
for parm in "$@"
do
echo $parm
done
执行脚本:sh /home/my_sh/param.sh 参数1 参数2 参数3 参数4 参数5
(4)$? : 最后一次执行的命令的返回状态。如果这个变量值为0,代表上一个命令正确执行。否则执行失败(具体是哪个数,由命令自己来决定)
测试:
sh /home/my_sh/hello.sh
echo $?
sh /home/my_sh/
echo $?
Shell的运算符
在Shell程序中,所有的数据类型默认是字符串,如果想要对数据进行运算,那么必须使用一定运算范式
例如:
命令:echo 1+1
并没有进行运算
(1) expr +、-、*、/、% 加、减、乘、除、取余
注意:expr运算符间要有空格
例如:
expr 1 + 1
expr 1 \* 2
expr 5 % 2
括号运算:(2+3)*6
命令:expr `expr 2 + 3` \* 6
(2) $((运算式))或$[运算式]
两种运算方式都是一样的,只是形式不同,都可以直接进行括号运算
例如:
echo $((1+1))
echo $((1*2))
echo $((5%2))
echo $(((2+3)*6))
echo $[1+1]
echo $[1*2]
echo $[5%2]
echo $[(2+3)*6]
Shell的条件判断
1、基本语法
[ condition ]
注意:condition前后一定要有空格,条件非空即为true,[ abc ] 返回true,[] 返回false
2、常用判断条件
(1)两个整数之间的比较
条件 | 解释 |
---|---|
-lt | 小于 (less than) |
-le | 小于等于 (less equal) |
-eq | 等于 (equal) |
-gt | 大于 (greater than) |
-ge | 大于等于 (greater equal) |
-ne | 不等于 (not equal) |
(2)按照文件权限进行判断
条件 | 解释 |
---|---|
-r | 有读权限的 (read) |
-w | 有写权限的 (write) |
-x | 有执行权限的 (execute) |
(3)按照文件类型进行判断
条件 | 解释 |
---|---|
-f | 文件存在并且是一个常规文件 (read) |
-e | 文件存在 (write) |
-d | 文件存在并且是一个目录 (execute) |
Shell的if语句
1、基本语法
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
注意:if和else if后都要跟空格,[ 条件 ] 条件前后也要加空格
2、测试
输入分数大于等于90打印优秀,小于90大于等于60打印及格,其它的输出太菜了
创建if.sh脚本:vim /home/my_sh/if.sh
输入以下内容
#!/bin/bash
if [ $1 -ge 90 ]
then
echo 优秀
elif [ $1 -ge 60 ]
then
echo 及格
else
echo 太菜了
fi
运行程序:
sh /home/my_sh/if.sh 90
sh /home/my_sh/if.sh 70
sh /home/my_sh/if.sh 60
sh /home/my_sh/if.sh 50
Shell的case语句
1、基本语法
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
"值3")
如果变量的值等于值1,则执行程序3
;;
*)
如果变量的值都不等于以上的值,则执行该程序
;;
esac
解释:
case开头,esac结尾。
对于每个分支,以两个分号结尾
2、测试
输入一个参数
参数如果为1,打印 你好,张三
参数如果为2,打印 你好,李四
参数如果为3,打印 你好,王五
参数如果为其它,打印 谁啊你
创建case.sh脚本:vim /home/my_sh/case.sh
输入以下内容:
#!/bin/bash
case $1 in
1)
echo 你好,张三
;;
2)
echo 你好,李四
;;
3)
echo 你好,王五
;;
*)
echo 谁啊你
;;
esac
执行程序:
sh /home/my_sh/case.sh 1
sh /home/my_sh/case.sh 2
sh /home/my_sh/case.sh 3
sh /home/my_sh/case.sh 4
Shell的for语句
1、两种for语法
#for循环方法1
for((初始值;循环控制条件;变量变化))
do
程序
done
#for循环方法2
for 变量名 in 集合名
do
程序
done
2、测试
两种for循环求1+2+3+…+99+100的值
创建for.sh脚本:vim /home/my_sh/for.sh
输入以下内容:
#!/bin/bash
#for循环方法1
sum1=0
sum2=0
for((i=1;i<=100;i++))
do
sum1=$[$sum1+$i]
done
#for循环方法2
for i in {1..100}
do
sum2=$[$sum2+$i]
done
echo sum1=$sum1
echo sum2=$sum2
执行程序:sh /home/my_sh/for.sh
Shell的while语句
1、基本语法
while [ 条件判断式 ]
do
程序
done
2、测试
while循环求1+2+3+…+99+100的值
创建while.sh脚本:vim /home/my_sh/while.sh
输入以下内容:
#!/bin/bash
sum=0
i=1
while [ $i -le 100 ]
do
sum=$[$sum+$i]
i=$[$i+1]
done
echo sum=$sum
Shell控制台输入
1、基本语法
read (选项) (参数)
选项:
选项 | 解释 |
---|---|
-p | 指定读取值时的提示符 |
-t | 指定读取值时等待的时间 |
参数:
变量:指定的读取值的变量名
2、示例
创建read.sh脚本:vim /home/my_sh/read.sh
输入以下内容:
#!/bin/bash
read -t 10 -p "请在10秒钟内输入您的姓名 " name
echo 您的名字为 $name
可以看到10秒钟不输入的话会跳过输入,继续执行后面的代码
Shell的系统函数
1、basename基本用法
basename [string/pathname] [suffix]
说明:
(1) basename命令会删除掉所有的前缀包括最后一个 ’/‘ 字符,然后以字符串的形式显示出来
(2) suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉
2、basename示例
截取 /home/mysql/data.txt 路径的文件名称
命令:
basename /home/mysql/data.txt
basename /home/mysql/data.txt .txt
3、dirname基本用法
dirname 文件绝对路径
说明:
(1) dirname从给定的包含绝对路径的文件名中去除文件名,然后返回剩下的路径。
3、dirname示例
截取 /home/mysql/data.txt 文件的路径名称
命令:dirname /home/mysql/data.txt
Shell自定义函数
1、基本语法
#方式1
function funname
{
Action
return int
}
#方式2
funname()
{
Action
return int
}
2、说明
(1) 必须在调用函数地方之前,先声明函数,shell脚本是逐行运行的。不会像其它语言一样先编译。
(2) 函数返回值,只能通过 $? 系统变量获得,可以显示加 return 返回,如果不加,将以最后一条命令运行结果(执行正确为0,执行错误为其它),作为返回值。return 后跟数值 n(0-255)
3、测试
fun函数接收任意个参数,求参数的和
创建my_fun.sh脚本:vim /home/my_sh/my_fun.sh
输入以下内容:
#!/bin/bash
function getsum
{
sum=0
for i in $@
do
((sum+=i))
done
return $sum
}
getsum 10 55 20
echo $?
运行脚本:sh /home/my_sh/my_fun.sh
e m s p ; emsp; emsp;emsp;此处我们借助 return 关键字将所有数字的和返回,并使用$?得到这个值,这种处理方案在其它编程语言中没有任何问题,但是在 Shell 中是非常错误的,Shell 函数的返回值和其它编程语言大有不同,返回值0代表程序执行没有异常,其它代表着程序执行失败
e m s p ; emsp; emsp;emsp;所以不应该这样使用返回值,可以直接在函数中打印数据
编辑my_fun.sh脚本:vim /home/my_sh/my_fun.sh
输入以下内容:
#!/bin/bash
function getsum
{
sum=0
for i in $@
do
((sum+=i))
done
echo sum=$sum
}
getsum 10 55 20
echo 返回值=$?
运行脚本:sh /home/my_sh/my_fun.sh
Shell工具——Cut
cut就是就是剪的意思,该工具就是剪切数据用的。cut命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出
1、基本用法
cut [选项参数] filename
参数 | 功能 |
---|---|
-f | 符号,提取第几列 |
-d | 分隔符,按照指定分割符分割列 |
2、准备数据
创建data.txt数据:vim /home/my_sh/data.txt
输入以下内容:
ni hao a
hello world !
shen zhen guan
3、测试
命令:
cut -d " " -f 1 /home/my_sh/data.txt
cut -d " " -f 1,2 /home/my_sh/data.txt
cut -d " " -f 1,3 /home/my_sh/data.txt
Shell工具——Sed
sed是一种流编辑器,它是一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,称为 “模式空间” ,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,不断重复,知道文件末尾。文件内容并没有改变,除非使用重定向存储输出
1、基本用法
sed [选项参数] ‘command’ filename
选项参数:
参数 | 功能 |
---|---|
-e | 直接在指令列模式上进行sed动作编辑 |
命令功能描述:
命令 | 功能描述 |
---|---|
a | 新增,a的后面可以接字符串,前面接数字,代表在第几行后面加上该字符串 |
d | 删除 |
s | 查找并替换 |
2、测试
(1) 在第二行后面添加“ni wo ta”
sed "2a ni wo ta" /home/my_sh/data.txt
(2) 删除包含 hello 的行
sed "/hello/d" /home/my_sh/data.txt
(3) 将文中所有的 hello 替换为 hi
sed "s/hello/hi/g" /home/my_sh/data.txt
g是global,全局的意思
(4) 删除第一行,将文中所有的 hello 替换为 hi
sed -e "1d" -e "s/hello/hi/g" /home/my_sh/data.txt
用-e执行多个流命令即可
Shell工具——Awk
一个强大的文本分析工具,把文件逐行读入,以空格为默认分隔符,将每行切片,切开的部分再进行分析处理。
1、基本语法
awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename
pattern: 表示AWK在数据中查找的内容,就是匹配模式
action: 在找到匹配内容时所执行的一系列命令
参数 | 功能 |
---|---|
-F | 指定输入文件的分隔符 |
-v | 赋值一个用户定义变量 |
2、测试
(0) 搜索文件以 ni 开头的所有行,并输出该行的第1列和第3列,用 ‘,’ 分割
awk '/^ni/{print $1","$3}' /home/my_sh/data.txt
^ni是正则表达式,以ni开头的意思
(2) 显示第1和第3行,在第一行前面添加“hei hei”,在最后一行添加“ha ha”
awk 'BEGIN{print "hei hei"} {print $1,$3} END{print "ha ha"}' /home/my_sh/data.txt
BEGIN、END可以指定第一行、最后一行
3、awk的内置变量
变量 | 说明 |
---|---|
FILENAME | 文件名 |
NR | 已读的记录数 |
NF | 切割后列的个数 |
(1) 统计data.txt文件的文件名、行号和列数
awk '{print "文件名:" FILENAME ", 行号:" NR ", 列数:" NF}' /home/my_sh/data.txt
Shell工具——Sort
sort命令非常常用,作用是将文件内容排序输出
1、基本语法
sort (选项) 文件名
选项 | 说明 |
---|---|
-n | 按照数值得大小从小到大排序 |
-r | 以相反的顺序来排序 |
-t | 设置排序时所用得分隔字符 |
-k | 指定需要排序得列 |
2、测试
(1) data.txt文件按每行第1列从小到大排序
sort /home/my_sh/data.txt
分隔符默认为空格
(2) data.txt文件按每行第3列从大到小排序
sort -rk 3 /home/my_sh/data.txt
分开写也是可以的
sort -r -k 3 /home/my_sh/data.txt
Shell面试题
(1) 使用Linux命令查询file.txt中空行所在的行号
awk '/^$/{print NR}' file.txt
(2) 有文件chengji.txt内容如下:
张三 20
李四 40
王五 40
统计第二列的和
cat chengji.txt | awk -F " " '{sum+=$2} END{print sum}'
(3) shell脚本判断一个文件是否存在
#!/bin/bash
if [ -f $1 ]
then
echo "文件存在"
else
echo "文件不存在"
fi
(4) 如果给定字符串 variable=“User:123:321:/home/dir”,如何只用 echo 命令获取 home_dir ?
#方式1
echo ${variable#*:*:*:}
#方式2
echo ${variable##*:}
(5) 写出输出数字 0 到 100 中 3 的倍数(0 3 6 9 …)的命令
#方式1
for i in {0..100..3}; do echo $i; done
#方式2
for (( i=0; i<=100; i=i+3 )); do echo $i;done
觉得不错就点个赞吧!