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、基本用法
  1. 单引号包裹的都转为字符串;

  2. 双引号包裹的可以包含变量,先替换变量,再转为字符串

  3. 连续的字符串可以不使用双引号

  4. 字符串之内有空格,不连续的就要用单引号或双引号包裹起来,否则报错

#!/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垂直制表符
\\\\一个反斜杠\\0ddd1到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、 HOMEPWD、 S H E L L 、 SHELL、 SHELLUSER、$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相对应的参数被视为含有要被处理的转义序列之字符串
%cASCII字符。显示相对应参数的第一个字符
%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 编程规范

shell if 语句

shell脚本编程总结

代码片段:Shell脚本实现重复执行和多进程

Shell编程总结

Shell编程总结