linux shell脚本学习
创始人
2024-05-15 20:32:25
0

linux shell脚本学习笔记

文章目录

    • linux shell脚本学习笔记
  • 一、脚本入门
    • 1.我的第一个linux脚本
    • 2.关于date命令的知识
  • 二、shell脚本中的变量
    • 1、为什么脚本需要变量?
  • 三、shell脚本中的逻辑判断
  • 四、shell脚本中的循环
    • 1.for循环
    • 2.while循环
  • 五、shell脚本中的函数
  • 六、linux脚本习题练习
        • 1.编写shell脚本,计算1-100的和
        • 2.编写shell脚本,要求输入一个数字,然后计算出从1到输入数字的和,要求,如果输入的数字小于1,则重新输入,直到输入正确的数字为止;
        • 3.编写shell脚本,把/root/目录下的所有目录(只需要一级)拷贝到/tmp/目录下;
        • 4.编写shell脚本,批量建立用户user_00, user_01, ... user_100并且所有用户同属于users组;
        • 5.编写shell脚本,截取文件test.log中包含关键词 ‘abc’ 的行中的第一列(假设分隔符为 ”:” ),然后把截取的数字排序(假设第一列为数字),然后打印出重复次数超过10次的列;
        • 6.编写shell脚本,判断输入的IP是否正确(IP的规则是,n1.n2.n3.n4,其中1

一、脚本入门

1.我的第一个linux脚本

#! /bin/bash## this is my first shell script
## writen by liu2023-01-22date
echo "hello world!"

​ Shell脚本通常都是以.sh 为后缀名的,这个并不是说不带.sh这个脚本就不能执行,只是大家的一个习惯而已。所以,以后您发现了.sh为后缀的文件那么它可能是一个shell脚本了。test.sh中第一行要以 “#! /bin/bash” 开头,它代表的意思是,该文件使用的是bash语法

接下来还需要为刚建立的脚本文件添加可执行权限

[root@localhost sbin]# ll
total 4
-rw-r--r--. 1 root root 101 Jan 22 11:30 first.sh
[root@localhost sbin]# chmod +x first.sh //添加可执行权限
[root@localhost sbin]# ./first.sh//执行该脚本
Sun Jan 22 11:31:42 CST 2023
hello world!

此外还有一种脚本执行的方法

[root@localhost sbin]# sh first.sh
Sun Jan 22 11:47:39 CST 2023
hello world!
[root@localhost sbin]#

要想使用该种方法运行shell脚本,前提是脚本本身有执行权限,所以需要给脚本加一个 ‘x’ 权限。另外使用sh命令去执行一个shell脚本的时候是可以加-x选项来查看这个脚本执行过程的,这样有利于我们调试这个脚本哪里出了问题:

[root@localhost sbin]# sh -x first.sh
+ date
Sun Jan 22 11:43:15 CST 2023
+ echo 'hello world!'
hello world!
[root@localhost sbin]#

2.关于date命令的知识

[root@localhost sbin]# date +"%Y-%m-%d %H:%M:%S"
2023-01-22 11:49:35

由此可见date用于输出时间

date在脚本中最常用的几个方法

  • date +%Y 以四位数字格式打印年份
  • date +%y 以两位数字格式打印年份
  • date +%m 月份
  • date +%d 日期
  • date +%M分钟
  • date +%S 秒
  • date +%w 星期,如果结果显示0则表示周日

有时在脚本中会使用到一天前的日期

[root@localhost sbin]# date -d "-1 day" +%d
21

或者一个小时之前

[root@localhost sbin]# date -d "-1 hour" +%H
10

甚至是1分钟之前

[root@localhost sbin]# date -d "-1 min" +%M
58

二、shell脚本中的变量

1、为什么脚本需要变量?

​ 在shell脚本中使用变量显得我们的脚本更加专业更像是一门语言,变量的作用当然不是为了专业。如果您写了一个长达1000行的shell脚本,并且脚本中出现了某一个命令或者路径几百次。突然您觉得路径不对想换一下,那岂不是要更改几百次?您固然可以使用批量替换的命令,但也是很麻烦,并且脚本显得臃肿了很多。变量的作用就是用来解决这个问题的。

我们来编写一个脚本使用到变量
#! /bin/bash##In this script we will use variablesd=`date +%H:%M:%S`
echo "The script begin at $d."
echo "Now we will sleep 2 seconds"
sleep 2
d1=`date +%H:%M:%S`
echo "The script end at $d1."

​ 脚本中使用到了反引号,您是否还记得它的作用? ‘d’ 和 ‘d1’ 在脚本中作为变量出现,定义变量的格式为 变量名=变量的值 当在脚本中引用变量时需要加上 ‘$’ 符号,这跟前面讲的在shell中自定义变量是一致的。下面看看脚本执行结果吧:

[root@localhost sbin]# ./variable.sh
The script begin at 12:14:37.
Now we will sleep 2 seconds
The script end at 12:14:39.

下面我们使用一个脚本来计算两个数的和

#! /bin/bash## this script is use to sum two numbersa=1
b=2sum=$[$a+$b]
echo "$a+$b=$sum"

数学计算要用[ ]括起来并且外头要带一个 ‘$’ 脚本结果为:

[root@localhost sbin]# ./sum.sh
1+2=3

使用脚本进行交互

vim read.sh
#! /bin/bash##Using 'read' in shell scriptread -p "Please input a number:" x
read -p "Please input another  number:" y
sum=$[$x+$y]
echo "The sum of the two numbers is: $sum!"

read 命令就是用在这样的地方,用于和用户交互,把用户输入的字符串作为变量值。

执行结果:

[root@localhost sbin]# chmod +x read.sh
[root@localhost sbin]# ./read.sh
Please input a number:12
Please input another  number:567
The sum of the two numbers is: 579!

有时候我们会用到这样的命令 /etc/init.d/iptables restart 前面的/etc/init.d/iptables文件其实就是一个shell脚本,为什么后面可以跟一个 “restart”? 这里就涉及到了shell脚本的预设变量。实际上,shell脚本在执行的时候后边是可以跟参数的,而且还可以跟多个。

#! /bin/bashsum=$[$1+$2]
echo "sum=$sum"

脚本执行结果如下:

[root@localhost sbin]# ./option.sh 1 2
sum=3
[root@localhost sbin]# ./option.sh 4 5
sum=9

在脚本中,您会不会奇怪,哪里来的$1和$2,这其实就是shell脚本的预设变量,其中$1的值就是在执行的时候输入的1,而$2的值就是执行的时候输入的$2,当然一个shell脚本的预设变量是没有限制的,这回您明白了吧。另外还有一个$0,不过它代表的是脚本本身的名字。不妨把脚本修改一下:

#! /bin/bash#sum=$[$1+$2]
echo "$1 $2 $0"

执行结果如下:

[root@localhost sbin]# ./option.sh 1 2
1 2 ./option.sh

三、shell脚本中的逻辑判断

如果您学过C或者其他语言,相信您不会对 if 陌生,在shell脚本中我们同样可以使用 if 逻辑判断。在shell中if判断的基本语法为:

1)不带else

if 判断句; thencommad
fi   

例如:

#! /bin/bashread -p "Please input your score:" a
if((a<60));thenecho "You did't pass the exam"
fi

执行结果如下:

[root@localhost sbin]# chmod +x if1.sh
[root@localhost sbin]# ./if1.sh
Please input your score:34#这里自己输入一个分数
You did't pass the exam

在if1.sh中出现了 ((a<60)) 这样的形式,这是shell脚本中特有的格式,用一个小括号或者不用都会报错,请记住这个格式。执行结果为:

2)带有else

if 判断语句 ; thencommand
elsecommand
fi:   

例如:

#! /bin/bashread -p "Please input your score: " a
if ((a<60)); thenecho "You didn't pass the exam."
elseecho "Good! You passed the exam."
fi

执行结果:

[root@localhost sbin]# chmod +x if2.sh
[root@localhost sbin]# ./if2.sh
Please input your score: 78
Good! You passed the exam.
[root@localhost sbin]# ./if2.sh
Please input your score: 23
You didn't pass the exam.
[root@localhost sbin]#

和上一例唯一区别的地方是,如果输入大于等于60的数字会有所提示。

3)带有elif

if 判断语句一 ; thencommad 
elif 判断语句二; thencommand
elsecommand
fi    

例如:

#! /bin/bashread -p "Please input you score: " a
if ((a<60)); thenecho "You didn't pass the exam."
elif ((a>=60))&&((a<85)); thenecho "Good! You pass the exam"
elseecho "very good! your score is very high"
fi

这里的 && 表示 “并且” 的意思,当然也可以使用 || 表示 “或者” 执行结果为:

[root@localhost sbin]# chmod +x ifs.sh
[root@localhost sbin]# ./ifs.sh
Please input you score: 90
very good! your score is very high
[root@localhost sbin]# ./ifs.sh
Please input you score: 78
Good! You pass the exam
[root@localhost sbin]# ./ifs.sh
Please input you score: 34
You didn't pass the exam.

以上只是简单的介绍了if语句的结构。在判断数值大小除了可以用 (( )) 的形式外,还可以使用 [ ] 但是就不能使用>, < , = 这样的符号了,要使用 -lt (小于),-gt (大于),-le (小于等于),-ge (大于等于),-eq (等于),-ne (不等于)

[root@localhost sbin]# a=10;if [ $a -lt 5 ]; then echo ok ; fi
[root@localhost sbin]# a=10;if [ $a -gt 5 ]; then echo ok ; fi
ok
[root@localhost sbin]# a=10;if [ $a -ge 5 ]; then echo ok ; fi
ok
[root@localhost sbin]# a=10;if [ $a -eq 5 ]; then echo ok ; fi
[root@localhost sbin]# a=10;if [ $a -eq 10 ]; then echo ok ; fi
ok
[root@localhost sbin]# a=10;if [ $a -ne 10 ]; then echo ok ; fi
[root@localhost sbin]#

再看看if中使用 && 和 ||的情况:

[root@localhost sbin]# a=10; if [ $a -lt 1 ] || [ $a -gt 5]; then echo ok; fi
-bash: [: missing `]'
[root@localhost sbin]# a=10; if [ $a -lt 1 ] || [ $a -gt 5 ]; then echo ok; fi
ok
[root@localhost sbin]# a=10; if [ $a -gt 1 ] || [ $a -lt 10 ]; then echo ok; fi
ok
[root@localhost sbin]#

shell 脚本中if还经常判断关于档案属性,比如判断是普通文件还是目录,判断文件是否有读写执行权限等。常用的也就几个选项:

  • -e : 判断文件或目录是否存在
  • -d: 判断是不是目录,并是否存在
  • -f: 判断是否是普通文件,并存在
  • -r: 判断文档是否有读权限
  • -w :判断是否有写权限
  • -x:判断是否可执行

使用if判断时,具体格式为:

if[ -e filename ] ; then 

例子:

[root@localhost sbin]# if [ -d /home/ ]; then echo "it is a directory"; fi
it is a directory
[root@localhost sbin]# if [ -f /home/ ]; then echo "it is a directory"; fi
[root@localhost sbin]#
因为/home/是一个目录而不是一个文件

其他的例子;

[root@localhost ~]# if [ -f /root/test.txt ]; then echo ok; fi
ok
[root@localhost ~]# if [ -r /root/test.txt ]; then echo yes; fi
yes
[root@localhost ~]# if [ -w /root/test.txt ]; then echo yes; fi
yes
[root@localhost ~]# if [ -x /root/test.txt ]; then echo yes; fi
[root@localhost ~]# if [ -e /root/test.txt ]; then echo yes; fi
yes
[root@localhost ~]#

在Shell脚本中,除了用if来判断逻辑外,还有一种常用的方式,那就是case了。具体格式为:

case 变量 in
value1)command;;
value2)command;;
value3)command;;
*)command;;
esac      

上面的结构中,不限制value的个数,*则代表除了上面的value外的其他值。

例子:

vim case.sh
#! /bin/bashread -p "Input a number: " n
a=$[$n%2]
case $a in1)echo "The number is odd.";;0)echo "The number is even.";;*)echo "It's not a number!";;
esac

$a的值或为1或为0,执行结果为:

[root@localhost sbin]# chmod +x case.sh
[root@localhost sbin]# ./case.sh
Input a number: 1
The number is odd.
[root@localhost sbin]# ./case.sh
Input a number: 2
The number is even.
[root@localhost sbin]# ./case.sh
Input a number: 3
The number is odd.
[root@localhost sbin]#

case脚本常用于编写系统服务的启动脚本,例如/etc/init.d/iptables中就用到了,您不妨去查看一下

四、shell脚本中的循环

Shell脚本中也算是一门简易的编程语言了,当然循环是不能缺少的。常用到的循环有for循环和while循环。下面就分别介绍一下两种循环的结构。

1.for循环

#! /bin/bashfor i in `seq 1 5 ` ; doecho $i
done

脚本中的 seq 1 5 表示从1到5的一个序列。您可以直接运行这个命令试下。脚本执行结果为:

[root@localhost sbin]# chmod +x for.sh
[root@localhost sbin]# ./for.sh
1
2
3
4
5
[root@localhost sbin]#

通过此脚本我们就可以看到for循环的基本结构

for 变量名 in 循环条件; docommand
done    

这里的 “循环的条件” 可以写成一组字符串或者数字(用1个或者多个空格隔开), 也可以是一条命令的执行结果:

[root@localhost sbin]# for i in 1 2 3 a b ; do echo $i; done
1
2
3
a
b

也可以写引用系统命令的执行结果,就像那个seq 1 5 但是需要用反引号括起来

[root@localhost sbin]# for file in `ls` ; do echo $file ; done
case.sh
first.sh
for.sh
if1.sh
if2.sh
ifs.sh
option.sh
read.sh
sum.sh
variable.sh

2.while循环

#! /bin/basha=5
while [ $a -ge 1 ]; doecho $aa=$[$a-1]
done

执行结果为:

[root@localhost sbin]# ./while.sh
5
4
3
2
1

while循环的格式也很简单

while 条件;docommand
done      

此外 我们也可以将循环条件用一个冒号进行替代,这样的话就可以做到死循环

while :; docommandsleep 3
done    

while命令

#! /bin/bash
a=1
while :; doecho "$a"a=$[$a+1]
sleep 3
done
这个代码可以用来写死循环

执行结果如下:

[root@localhost sbin]# ./while5.sh
1
2
3
...

五、shell脚本中的函数

函数就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段代码时直接调用这个小单元的名字即可。有时候脚本中的某段代总是重复使用,如果写成函数,每次用到时直接用函数名代替即可,这样就节省了时间还节省了空间。

案例:

#! /bin/bashfunction sum()
{sum=$[$1+$2]echo $sum
}sum $1 $2

执行结果如下

[root@localhost sbin]# ./func.sh 1 2
3

由func.sh中的sum()为自定义的函数,在shell脚本函数的格式为:

function 函数名(){
command
}

注意点:在shell脚本中,函数一定要写在最前面,不能出现在中间或者最后,因为函数是要被调用的,如果还没有出现就被调用,肯定是会出错的。

六、linux脚本习题练习

1.编写shell脚本,计算1-100的和

vim first.sh
#! /bin/bash
sum=0
a=1
#using function while
function sumwhile(){while [ $a -le 100 ];dosum=$[$sum+$a]a=$[$a+1]
done
echo "the sumwhile of 1~100 is:" $sum
}#using function for
function forsum(){for i in `seq 1 100`;dosum=$[$sum+$i]
done
echo "the sumfor of 1~100 is :" $sum
}sumwhile
# forsum

脚本执行结果:

[root@localhost shells]# ./first.sh
the sumfor of 1~100 is : 5050
[root@localhost shells]# vim first.sh
[root@localhost shells]# ./first.sh
the sumwhile of 1~100 is: 5050

2.编写shell脚本,要求输入一个数字,然后计算出从1到输入数字的和,要求,如果输入的数字小于1,则重新输入,直到输入正确的数字为止;

代码:

vim second.sh
#! /bin/bash
a=0
while [ $a -lt "1" ]; do
read -p "please input a number,it must greater than "1": " a
donesum=0while [ $a -ge 1 ];dosum=$[$sum+$a]a=$[$a-1]done
echo "sum is: " $sum

运行结果:

[root@localhost shells]# ./second.sh
please input a number,it must greater than 1: -5#不符合条件,要求重新输入
please input a number,it must greater than 1: 9
sum is:  45

3.编写shell脚本,把/root/目录下的所有目录(只需要一级)拷贝到/tmp/目录下;

#! /bin/bashcd /root/
for f in `ls`; doif [ -d $f ] ; thencp -r $f /tmp/fi
done

4.编写shell脚本,批量建立用户user_00, user_01, … user_100并且所有用户同属于users组;

#! /bin/bashgroupadd usersfor i in `seq 0 9`; douseradd -g users user_0$i
donefor j in `seq 10 100`; douseradd -g users user_$j
done

执行结果如下:

cat /etc/passwd
user_00:x:1000:100::/home/user_00:/bin/bash
user_01:x:1001:100::/home/user_01:/bin/bash
user_02:x:1002:100::/home/user_02:/bin/bash
user_03:x:1003:100::/home/user_03:/bin/bash
user_04:x:1004:100::/home/user_04:/bin/bash
user_05:x:1005:100::/home/user_05:/bin/bash
user_06:x:1006:100::/home/user_06:/bin/bash
user_07:x:1007:100::/home/user_07:/bin/bash
user_08:x:1008:100::/home/user_08:/bin/bash
...

5.编写shell脚本,截取文件test.log中包含关键词 ‘abc’ 的行中的第一列(假设分隔符为 ”:” ),然后把截取的数字排序(假设第一列为数字),然后打印出重复次数超过10次的列;

#! /bin/bashawk -F':' '$0~/abc/ {print $1}' test.log >/tmp/n.txt
sort -n n.txt |uniq -c |sort -n >/tmp/n2.txt
awk '$1>10 {print $2}' /tmp/n2.txt

6.编写shell脚本,判断输入的IP是否正确(IP的规则是,n1.n2.n3.n4,其中1
#! /bin/bash#now we write a function
checkip() {# if echo $1 |egrep -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' ; thenif echo $1 |egrep -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' ; thena=`echo $1 | awk -F. '{print $1}'`b=`echo $1 | awk -F. '{print $2}'`c=`echo $1 | awk -F. '{print $3}'`d=`echo $1 | awk -F. '{print $4}'`for n in $a $b $c $d; doif [ $n -ge 255 ] || [ $n -le 0 ]; thenecho "the number of the ip should less than 255 and greater than 0"return 2fidoneelseecho "The ip you input is something wrong ,the format is like 192.168.100.1"return 1fi
}rs=1
while [ $rs -gt 0 ]; doread -p "Please input the ip:" ipcheckip $iprs=`echo $?`
doneecho "The ip is right!"

执行结果如下:

[root@localhost shells]# sh -x six4.sh
+ rs=1
+ '[' 1 -gt 0 ']'
+ read -p 'Please input the ip:' ip
Please input the ip:192.168.20.2
+ checkip 192.168.20.2
+ echo 192.168.20.2
+ egrep -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
++ echo 192.168.20.2
++ awk -F. '{print $1}'
+ a=192
++ echo 192.168.20.2
++ awk -F. '{print $2}'
+ b=168
++ echo 192.168.20.2
++ awk -F. '{print $3}'
+ c=20
++ echo 192.168.20.2
++ awk -F. '{print $4}'
+ d=2
+ for n in '$a' '$b' '$c' '$d'
+ '[' 192 -ge 255 ']'
+ '[' 192 -le 0 ']'
+ for n in '$a' '$b' '$c' '$d'
+ '[' 168 -ge 255 ']'
+ '[' 168 -le 0 ']'
+ for n in '$a' '$b' '$c' '$d'
+ '[' 20 -ge 255 ']'
+ '[' 20 -le 0 ']'
+ for n in '$a' '$b' '$c' '$d'
+ '[' 2 -ge 255 ']'
+ '[' 2 -le 0 ']'
++ echo 0
+ rs=0
+ '[' 0 -gt 0 ']'
+ echo 'The ip is right!'
The ip is right!

相关内容

热门资讯

虞书欣谈成名的代价令人心疼,如... 虞书欣谈成名的代价令人心疼,如今她在圈内的前景如何?虞书欣在圈内前景是很不错的,大家都很喜欢她,也有...
最有效的减肥食谱 最有效的减肥食谱谁有最有效的减肥食谱呢?麻烦给一个吧?急求最有效的减肥食谱,听说有一个什么汤的可以很...
关晓彤鹿晗被曝月底会分手,你对... 关晓彤鹿晗被曝月底会分手,你对于他们两个的爱情有什么看法?当初我也觉得他们俩的感情肯定不会长久的,但...
她曾在家中喂猪,却被张艺谋相中... 她曾在家中喂猪,却被张艺谋相中一夜成名,魏敏芝如今过得怎样?魏敏芝过得非常不错啊,而且当地的头衔也是...
电影《中邪》主要讲了什么? 电影《中邪》主要讲了什么?中邪的剧情简介 · · · · · ·大学生丁鑫和刘梦为拍摄农村风俗纪录片...
可以在营业厅查到短信的内容吗? 可以在营业厅查到短信的内容吗?查自己的短信==如果你是本人应该可以…不是本人是不可以的那是别人的隐私...
春日时雨时晴,杏花开时,小雨落... 春日时雨时晴,杏花开时,小雨落在身上,衣服欲湿未湿;杨柳风最柔,吹到脸上也下觉其寒。是什么诗句沾衣欲...
低学历的女人真的不能娶吗? 低学历的女人真的不能娶吗?我觉得不是的,娶妻子还是主要看对方的品性如何,而不是在意对方的学历。不一定...
电影配音问题 懂的进来 不是很... 电影配音问题 懂的进来 不是很难我想知道一个问题 比如说 一个电影 演员是 X 那他的说...可以是...
关于大蒜的谜语有哪些 关于大蒜的谜语有哪些有关蒜的谜语有:两二小,头长草 (打字一)谜底:蒜弟兄七八个,围着柱子坐,只要一...
怎么夸老师漂亮 怎么夸老师漂亮老师您长得太有气质了,非常出众,我身为一个女孩子都快要把持不住了。就直接一点说:老师你...
一般怎么钢琴即兴伴奏,一拿到简... 一般怎么钢琴即兴伴奏,一拿到简谱就能伴奏的和弦 天空之城简易般的可一参考 摸摸就出来的 弹一个音 ...
我对异地女友说,异地太苦了我真... 我对异地女友说,异地太苦了我真心问你,你和我一起内心快乐吗?她说,不管日子再苦,有你就是甜的?你一个...
为什么叫镇江 为什么叫镇江为什么叫镇江意义为"Garrison of the Yangtze River"
在足球历史上,阿贾克斯都获得过... 在足球历史上,阿贾克斯都获得过多少次欧冠?一共应该是获得过4次冠军,而且他真的是特别厉害,很少有人可...
时间简史是谁写的? 时间简史是谁写的?史蒂芬·威廉·霍金
我爱她,但她爱他。 我爱她,但她爱他。如果换了我是你!我会一直的爱着她!她爱着他,你又爱着他!她知道爱一个不爱自己人的资...
歌词:我是你的月亮,是你夜里的... 歌词:我是你的月亮,是你夜里的光芒。叫月光曲,嘿嘿
枪神纪里面的英文歌曲叫什么? 枪神纪里面的英文歌曲叫什么?枪神纪里面的英文歌曲叫什么?一首是男的一首是女的,女的那首好像有一句是,...
中外小朋友 大家手拉手 来自五... 中外小朋友 大家手拉手 来自五大洲 是什么歌名?中外小朋友 大家手拉手 来自五大洲 是什么歌名?《庆...