shell编程总结
Posted 玩家_名狱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell编程总结相关的知识,希望对你有一定的参考价值。
一、开始运行
首先在文件开头添加使用#!/bin/bash
,意思是使用该shell解释器运行该脚本
echo命令用于输出一句话
#!/bin/bash
echo "Hello world !!!"
然后可以有多种运行shell脚本的方法
1、sh命令运行
root@zxh:~# sh test.sh
2、bash命令运行
root@zxh:~# bash test.sh
3、./方式运行
sh和bash命令都是把当前脚本文件输出给/bin/bash运行,所以只要我们有使用/bin/bash的权限,就能运行。但是使用./的方式运行,就等于直接将本文件输出给系统的解释器运行,此时就需要本文件有执行的权限,所以要先提权,再运行
root@zxh:~# chown 777 test.sh
root@zxh:~# ./test.sh
4、案例一
在当前目录下创建一个叫work.txt的文件,然后写入数据I Yove You。
#!/bin/bash
echo "start touch file!!!"
touch lian.txt
echo "I Love You" >> lian.txt
echo "stop commond!!!"
5、echo
打印字符串。
1、基本用法
-
单引号包裹的都转为字符串;
-
双引号包裹的可以包含变量,先替换变量,再转为字符串
-
连续的字符串可以不使用双引号
-
字符串之内有空格,不连续的就要用单引号或双引号包裹起来,否则报错
#!/bin/bash
echo "----------------------------"
a=吃了
echo '吃了吗$a'
echo "吃了吗$a"
echo 吃了吗$a
echo "吃 了吗$a"
echo "----------------------------"
root@zxh:~# ./test.sh
----------------------------
吃了吗$a
吃了吗吃了
吃了吗吃了
吃 了吗吃了
----------------------------
2、包含转义字符
要使用选项 -e
root@zxh:~# echo "hh\\thh"
hh\\thh
root@zxh:~# echo -e "hh\\thh"
hh hh
root@zxh:~# echo -e "hh\\0112hh"
hhJhh
root@zxh:~# echo -e "hh\\0113hh"
hhKhh
常见转义序列
字符 | 含义 | 字符 | 含义 |
---|---|---|---|
\\b | 后退 | \\f | 换页 |
\\n | 换行 | \\r | 回车 |
\\t | 水平制表符 | \\v | 垂直制表符 |
\\\\ | 一个反斜杠 | \\0ddd | 1到3位整数用于表示八进制的字符 |
root@iZbp18qtvejt7jqx8ghcanZ:~/code/shell_learn# echo -e "hh\\0112hh"
hhJhh
root@iZbp18qtvejt7jqx8ghcanZ:~/code/shell_learn# echo -e "hh\\0113hh"
hhKhh
3、颜色
文字颜色。使用 \\e[1;XXm 和 \\e[0m 包裹,中间的文字会变色,XX代表从30-37的数字
#!/bin/bash
echo -e "\\e[1;31m你好\\e[0m呀"
echo -e "\\e[1;36m你好\\e[0m呀"
echo -e "\\e[1;33m你好\\e[0m呀"
文字颜色码 | 颜色 | 文字颜色码 | 颜色 |
---|---|---|---|
0 | 重置 | 30 | 黑色 |
31 | 红色 | 32 | 绿色 |
33 | 黄色 | 34 | 蓝色 |
35 | 洋红色 | 36 | 青色 |
37 | 白色 |
背景色。使用 \\e[1;YYm 和 \\e[0m 包裹,中间的部分背景会变色,YY代表从40-47的数字。默认文字为白色
#!/bin/bash
echo -e "\\e[1;42m你好\\e[0m呀"
echo -e "\\e[1;45m你好\\e[0m呀"
echo -e "\\e[1;46m你好\\e[0m呀"
文字颜色和背景色支持嵌套,只需要一个 \\e[0m 结尾即可
#!/bin/bash
echo -e "\\e[1;41m \\e[1;34m你好\\e[0m \\e[0m呀"
echo -e "\\e[1;41m \\e[1;34m你好 \\e[0m呀"
二、变量
1、普通变量的赋值、使用和取消
变量赋值。变量名=值,如a=2
,等号两边不能有空格
使用变量。** 变 量 名 ∗ ∗ , 如 ‘ 变量名**,如 ` 变量名∗∗,如‘a`
#!/bin/bash
echo "----------------------------"
p=$USER
echo $p
echo "----------------------------"
#结果
#----------------------------
#root
#----------------------------
取消变量的使用。unset命令
#!/bin/bash
echo "----------------------------"
p=$USER
unset p
echo $p
echo "----------------------------"
#结果
#----------------------------
#
#----------------------------
只读变量。普通变量可以被取消,但是可以定义一个只读变量,除非系统重启,否则不可被取消
#!/bin/bash
echo "----------------------------"
readonly p=$USER
unset p
echo $p
echo "----------------------------"
#结果
#----------------------------
#./one.sh: line 4: unset: p: cannot unset: readonly variable
#root
#----------------------------
变量默认为字符串类型,不能进行数值运算
#!/bin/bash
echo "----------------------------"
p=1+5
echo $p
echo "----------------------------"
#结果
#----------------------------
#1+5
#----------------------------
定义的字符串中间有空格就要使用单引号或双引号括起来
#!/bin/bash
echo "----------------------------"
n=hello world
echo $n
y="hello world"
echo $y
echo "----------------------------"
#结果
#----------------------------
#./one.sh: line 3: world: command not found
#
#hello world
#----------------------------
2、全局变量
a=2这种方式定义的变量只是普通的局部变量,该变量只能在该脚本运行时,且只能在该脚本内使用,其他脚本不能使用,因此可以直接定义全局变量(export n=1)或者提升普通变量为全局变量(n=1后export n)
#!/bin/bash
echo "----------------------------"
echo $n
echo "----------------------------"
root@zxh:~# ./one.sh
----------------------------
----------------------------
root@zxh:~# export n=1000000
root@zxh:~# ./one.sh
----------------------------
1000000
----------------------------
上面在脚本文件中输出变量n,但是没有定义这个n,运行时输出为空,在bash控制台设置全局变量,之后再次运行脚本,脚本就可以找到全局变量n了。
注意:
- 如果有同名的局部变量,优先使用局部变量
- 该全局变量的生命周期为脚本运行时,脚本关闭,该全局变量也就失效了
- bash控制台和自己写的脚本本质是一样的,也就是说,正在运行的控制台也是一个脚本
3、系统变量
常用的系统变量 H O M E 、 HOME、 HOME、PWD、 S H E L L 、 SHELL、 SHELL、USER、$PATH……。
- $HOME代表当前用户的家目录
- $PWD代表当前所在目录
- $SHELL代表使用的是哪个shell解释器
- $USER代表当前用户名
- $PATH代表系统变量
#!/bin/bash
echo "----------------------------"
echo $HOME
echo "----------------------------"
root@zxh:~# ./test.sh
----------------------------
/root
----------------------------
4、特殊变量(重点)
1)$number
参数 | 含义 |
---|---|
$0 | 脚本文件名字 |
$1 | 启动脚本时传的第一个参数 |
$2 | 启动脚本时传的第二个参数 |
$3 | 启动脚本时传的第三个参数 |
…… | …… |
$(10) | 启动脚本时传的第十个参数,十个或以上要用括号 |
$(11) | 启动脚本时传的第十一个参数 |
…… | …… |
#!/bin/bash
echo "----------------------------"
echo $0
echo $1
echo $2
echo "----------------------------"
root@zxh:~# ./test.sh 666 888
----------------------------
./test.sh
666
888
----------------------------
root@zxh:~# sh test.sh 666 888
----------------------------
test.sh
666
888
----------------------------
2)$#
获取所有输入参数个数(该参数常用于循环中)
#!/bin/bash
echo "----------------------------"
echo $#
echo "----------------------------"
root@zxh:~# ./test.sh 666 888
----------------------------
2
----------------------------
root@zxh:~# sh test.sh 666 888
----------------------------
2
----------------------------
3)$* 和 $@
$*代表命令行中所有的参数,把所有的参数看成一个不可区分的整体
$@代表命令行中所有的参数,把所有的参数看成一个可区分的整体(可用循环迭代)
具体区别,查看for循环的应用
4)$?
代表前面最后一次的命令的执行状态。
- 如果执行正常,结果为0
- 如果执行失败,结果不固定,由命令本身决定
#!/bin/bash
echo "----------------------------"
cat "hhhh"
echo "Error code: "$?
$?
echo "Error code: "$?
echo "yeye"
echo "Error code: "$?
echo "----------------------------"
#结果
#----------------------------
#cat: hhhh: No such file or directory
#Error code: 1
#test.sh: 5: test.sh: 0: not found
#Error code: 127
#yeye
#Error code: 0
#----------------------------
三、字符串操作
1、获取字符串长度
#!/bin/bash
data="myname"
echo ${#data}
#结果
#6
2、截取字符串
${变量名:位置起点} 。从起点到结束,起点从0开始
#!/bin/bash
data="myname"
echo ${data:2}
#结果
#name
${变量名:位置起点:长度} 。从起点到指定长度
#!/bin/bash
data="myname"
echo ${data:2:3}
#结果
#nam
3、替换字符串
${变量/样式/替换字符串} 。如果变量中有符合样式的字符串,则使用替换字符串替代该样式,只替换第一个符合的样式
#!/bin/bash
data="hello lili hello niuniu"
echo ${data/hello/good}
# 结果
#good lili hello niuniu
${变量//样式/替换字符串} 。如果变量中有符合样式的字符串,则使用替换字符串替代该样式,替换全部符合的样式
#!/bin/bash
data="hello lili hello niuniu"
echo ${data//hello/good}
# 结果
#good lili good niuniu
4、提取字符串
${变量#*样式} 。从最左边开始与样式比对 ,将寻找到的第一个作为分隔符,删除左边,只剩下右边字符串
#!/bin/bash
str="say hello python hello golang hello c"
echo ${str#*he}
#结果
#llo python hello golang hello c
${变量%样式*} 。从最右边开始与样式比对 ,将寻找到的第一个作为分隔符,删除右边,只剩下左边字符串
#!/bin/bash
str="say hello python hello golang hello c"
echo ${str%he*}
#结果
#say hello python hello golang
${变量##*样式} 。从最左边开始与样式比对 ,将寻找到的最后一个作为分隔符,删除左边,只剩下右边字符串
#!/bin/bash
str="say hello python hello golang hello c"
echo ${str##he*}
#结果
#llo c
${变量%%样式*} 。从最右边开始与样式比对 ,将寻找到的最后一个作为分隔符,删除右边,只剩下左边字符串
#!/bin/bash
str="say hello python hello golang hello c"
echo ${str%%he*}
#结果
#say
5、字符串拼接
#!/bin/bash
str1="hello"
str2="$str1 world"
str3=$str1$str2
echo $str2
echo $str3
#结果
#hello world
#hellohello world
四、运算符
1、expr
运算符可以使用 加(+)、减(-)、乘(\\*)、除(/)、余(%)。运算符间要有空格。可以嵌套,使用反引号括起来表示先运行
#!/bin/bash
echo "----------------------------"
expr `expr 2 + 4` \\* 5
echo "----------------------------"
#结果
#----------------------------
#30
#----------------------------
2、let
#!/bin/bash
num1=11
num2=22
let num3=num1+num2
echo $num3
let sum=11+22
echo $sum
#结果
#33
#33
3、bc计算器
bc计算器是系统内部的计算器,我们只要传计算式子给bc计算器即可,传递过程使用到管道符
#!/bin/bash
num1=7
num="(1+3)*4/2%$num1"
echo $num | bc
#结果
#1
2、$[表达式子]
运算符可以使用 **加(+)、减(-)、乘(*)、除(/)、余(%)**表达式内部没有空格。不能使用sh命令启动脚本
#!/bin/bash
echo "----------------------------"
s=$[(5+8)*2]
echo $s
echo "----------------------------"
root@zxh:~# ./test.sh
----------------------------
26
----------------------------
root@zxh:~# bash test.sh
----------------------------
26
----------------------------
root@zxh:~# sh test.sh
----------------------------
test.sh: 3: test.sh: Syntax error: "(" unexpected
3、$((表达式子))(常用)
表达式内对空格没有要求,使用小括号作为运算优先符号,常用这个方式作为运算式子
#!/bin/bash
echo "----------------------------"
s=$((((5 + 8) % 2) + 1))
echo $s
echo "----------------------------"
#结果
#----------------------------
#2
#----------------------------
五、条件判断
[ condition ],condition前后要有空格,condition为true或者false
1、两个整数之间的比较
符号 | 含义 |
---|---|
= | 字符串比较是否相同 |
-eq | 等于(equal) |
-lt | 小于(less than) |
-le | 小于等于(less equal) |
-gt | 大于(greater than) |
-ge | 大于等于(greater equal) |
-ne | 不等于(not equal) |
#!/bin/bash
echo "----------------------------"
echo '$?正确则为0,错误则为其他'
[ 33 -ge 11 ]
echo $?
[ 33 -le 11 ]
echo $?
echo "----------------------------"
#结果
#----------------------------
#$?正确则为0,错误则为其他
#0
#1
#----------------------------
root@zxh:~# [ "hhh" = "hh" ]
root@zxh:~# echo $?
1
root@zxh:~# [ "hhh" = "hhh" ]
root@zxh:~# echo $?
0
2、按照文件权限进行判断
符号 | 含义 |
---|---|
-r | 有读的权限(read) |
-w | 有写的权限(write) |
-x | 有执行的权限(execute) |
root@zxh:~# touch hhh.txt
root@zxh:~# [ -r hhh.txt ]
root@zxh:~# echo $?
0
root@zxh:~# [ -w hhh.txt ]
root@zxh:~# echo $?
0
root@zxh:~# [ -x hhh.txt ]
root@zxh:~# echo $?
1
3、按照文件类型进行判断
符号 | 含义 |
---|---|
-f | 文件存在并且是一个常规的文件(file) |
-e | 文件存在(existence) |
-d | 文件存在并且是一个目录(directory) |
-s | 文件大小是否大于0 |
root@zxh:~# touch hhh.txt
root@zxh:~# ls
hhh.txt test.sh
root@zxh:~# [ -f hhh.txt ]
root@zxh:~# echo $?
0
root@zxh:~# [ -e hhh.txt ]
root@zxh:~# echo $?
0
root@zxh:~# [ -e test.txt ]
root@zxh:~# echo $?
1
root@zxh:~# [ -d hhh.txt ]
root@zxh:~# echo $?
1
root@zxh:~# touch hhh.txt
root@zxh:~# [ -s hhh.txt ]
root@zxh:~# echo $?
1
root@zxh:~# echo "ni niu bi a" >> hhh.txt
root@zxh:~# [ -s hhh.txt ]
root@zxh:~# echo $?
0
4、复杂逻辑判断
符号 | 含义 |
---|---|
-a | 与 |
-o | 或 |
! | 非 |
root@zxh:~# [ 11 -lt 12 -a 12 -lt 13 ]
root@zxh:~# echo $?
0
root@zxh:~# [ 11 -lt 12 -a 12 -eq 13 ]
root@zxh:~# echo $?
1
六、流程控制(重点)
1、if判断
if 关键字后要跟一个空格,然后加条件判断,then 关键字可以写在下一行,也可以写在当前行,写在当前行前面要有分号。然后写程序。最后使用 fi 关键字结尾
if [ 表达式子 ];then
程序
elif [ 表达式子 ];then
程序
else
程序
fi
#-------或者--------
if [ 表达式子 ]
then
程序
elif [ 表达式子 ]
then
程序
else
程序
fi
#!/bin/bash
if [ $1 -gt 11 ]
then
echo "你输入的数字大于11"
elif [ $1 -eq 11 ]
then
echo "你输入的数字等于11"
else
echo "你输入的数字小于11"
fi
root@zxh:~# bash test.sh 10
你输入的数字小于11
root@zxh:~# bash test.sh 11
你输入的数字等于11
root@zxh:~# bash test.sh 12
你输入的数字大于11
2、case语句
case $变量名 in
"值1")
程序
;;
"值2")
程序
;;
"值3")
程序
;;
esac
#!/bin/bash
case $1 in
"11")
echo "你输入11"
;;
12)
echo "你输入12"
;;
"13")
echo "你输入13"
;;
esac
root@zxh:~# bash test.sh 11
你输入11
root@zxh:~# bash test.sh 12
你输入12
root@zxh:~# bash test.sh 13
你输入13
root@zxh:~# bash test.sh 14
3、for循环
第一种写法
for ((初始值;循环控制条件;变量变化))
do
程序
done
#!/bin/bash
sum=0
for ((i=1; i<=5; i++))
do
sum=$(($i+$sum))
done
echo $sum
#结果
#15
第二种写法
for 变量 in 值1 值2 值3……
do
程序
done
#!/bin/bash
for num1 in $*
do
echo $num1
done
for num2 in $@
do
echo $num2
done
root@zxh:~# ./test.sh 11 22 33
11
22
33
11
22
33
#!/bin/bash
for num1 in "$*"
do
echo $num1
done
for num2 in "$@"
do
echo $num2
done
root@zxh:~# ./test.sh 11 22 33
11 22 33
11
22
33
4、while循环
while [ 条件判断式 ]
do
程序
done
#!/bin/bash
i=1
while [ $i -le 4 ]
do
echo $i
i=$(($i + 1))
done
#结果
#1
#2
#3
#4
七、数组
1、数组的定义
变量名[下标]=值 或者 变量名=(值1 值2 值3……)
#!/bin/bash
arr=(666 777 888)
arr[3]=999
echo ${arr[*]}
#结果
#666 777 888 999
2、数组的访问
#!/bin/bash
arr=(666 777 888 999)
echo "数组的长度:"${#arr[*]}
echo "数组的第二个元素:"${arr[1]}
echo "数组的所有元素:"${arr[*]}
echo "数组的所有元素:"${arr[@]}
echo "数组的所有下标:"${!arr[*]}
echo "从第2个元素开始到结束:"${arr[*]:1}
echo "从第2个元素开始到后面1个:"${arr[*]:1:1}
#结果
#数组的长度:4
#数组的第二个元素:777
#数组的所有元素:666 777 888 999
#数组的所有元素:666 777 888 999
#数组的所有下标:0 1 2 3
#从第2个元素开始到结束:777 888 999
#从第2个元素开始到后面1个:777
3、删除数组元素
unset 数组名[下标] 。使用关键字unset删除数组元素,如果直接加数组名就是删除数组
#!/bin/bash
arr=(666 777 888 999)
unset arr[1]
echo "数组的长度:"${#arr[*]}
echo "数组的第二个元素:"${arr[1]}
echo "数组的所有元素:"${arr[*]}
echo "数组的所有下标:"${!arr[*]}
#结果
#数组的长度:3
#数组的第二个元素:
#数组的所有元素:666 888 999
#数组的所有下标:0 2 3
4、数组的修改
给定位置修改
#!/bin/bash
arr=(666 777 888 999)
arr[1]=555
echo ${arr[*]}
#结果
#666 555 888 999
查找替换修改
#!/bin/bash
arr=(666 777 888 999)
echo ${arr[*]/777/555}
#结果
#666 555 888 999
5、数组的遍历
#!/bin/bash
arr=(666 777 888 999)
unset arr[1]
for ((i = 0; i < ${#arr[@]}; i++)); do
echo ${arr[$i]}
done
echo "使用for(())的方式遍历时,若有元素被删除就遍历异常"
for j in ${arr[@]}; do
echo $j
done
echo "使用for in的方式遍历时,正常"
#结果
#666
#
#888
#使用for(())的方式遍历时,若有元素被删除就遍历异常
#666
#888
#999
#使用for in的方式遍历时,正常
七、read读取控制台输入
read (选项)(选项值) 变量名
选项:
- -p:指定读取值时,控制台的提示符
- -t:指定读取值时,等待的时间(秒)
变量名:用于接收控制台传来的值
#!/bin/bash
read -p "5秒内输入你所想:" -t 5 deam
echo $deam
root@zxh:~# ./test.sh
5秒内输入你所想:3456
3456
root@zxh:~# ./test.sh
5秒内输入你所想:
#不输入内容,5秒后自动关闭
八、printf输出
和C语言的printf函数类似
#!/bin/bash
a=100
printf "math:%-10d分\\n" $a
printf "math:%10d分\\n" $a
#结果
#math:100 分
#math: 100分
格式替代符如下表
符号 | 含义 |
---|---|
%b | 相对应的参数被视为含有要被处理的转义序列之字符串 |
%c | ASCII字符。显示相对应参数的第一个字符 |
%d或%i | 对应十进制数字格式 |
%e或%E或%f | 对应浮点格式 |
%o | 不带正负号的八进制值(字母O) |
%s | 字符串 |
%u | 不带正负号的十进制数 |
%% | 字面意义的% |
%x或(%X) | 不带正负号的十六进制数,a-f表示10-15(A-F表示10-15) |
同时也支持转义序列
九、函数
1、系统函数
类似php那样有很多系统函数,在shell解释器中就已有了,我们只要调用就行了
1)basename
basename [pathname] [suffix] 。给定一个路径字符串,然后取出文件名全称,suffix为后缀名,如果指定后缀名,则取出文件名后再去掉后缀名
root@zxh:~# basename ~/code/shell_learn/hhh.txt
hhh.txt
root@zxh:~# basename ~/code/shell_learn/hhh.txt .txt
hhh
root@zxh:~# basename ~/code/shell_learn/hhh.txt xt
hhh.t
2)dirname
dirname 文件绝对路径 。从给定的绝对路径中,去掉文件名,只留下目录部分
不能是相对路径,如 ./ 或 …/
root@zxh:~# dirname ~/code/shell_learn/hhh.txt
/root/code/shell_learn
root@zxh:~# dirname ./hhh.txt
.
root@zxh:~# dirname /root/code/shell_learn/hhh.txt
/root/code/shell_learn
3)sleep
自定义暂停时间
#!/bin/bash
echo "hello"
sleep 3.5
echo "hi"
#结果
#hello
# 这里等待3.5秒
#hi
2、自定义函数
基本格式:
[function] funname [( )]{
程序;
[return int;]
}
调用:
funname
- 先申明再调用
- 函数的返回值只能通过$?系统变量获得
- 如果不使用return语句返回数值,默认使用函数最后一条命令运行结果作为返回值
- return后面跟数值。(0 - 255)
#!/bin/bash
function sum(){
s=0
for i in $@
do
s=$(($s+$i))
done
Linux学习总结(79)—— Shell 编程规范