shell脚本编程之基础

简介: shell脚本编程之基础

1.使用多个命令


shell脚本的关键之处在于输入多个命令并处理每个命令的结果,甚至需要将一个命令的结果传给另一个命令。shell可以让多个命令串起来,一次执行。如果要两个命令一起运行,可以将它们放在同一行,之间用逗号隔开


1[njust@njust tutorials]$ date;who
22020年 03月 11日 星期三 22:39:16 CST
3njust    :0           2020-03-11 22:28 (:0)
4njust    pts/0        2020-03-11 22:35 (192.168.0.107)


上述方法的缺点:使用上述方法可以将任意多个命令串联在一起使用,最大命令行字符数不超过255个。对小型的脚本适用,当有很多脚本时,直接在命令行中输入整个命令就很麻烦。


2.创建shell脚本文件


创建shell脚本文件时,必须在文件的第一行指定使用的shell是哪种类型,格式为:


1#!/bin/bash


shell脚本中注释一般以#开头,shell脚本不会处理注释的行。但是,shell脚本的第一行是例外。#后的!会告诉shell用哪个shell来运行脚本,shell会根据命令在文件中出现的先后顺序进行处理。下面是创建脚本名为demo的文件。


1#!/bin/bash
2date
3who


存在的问题:如何让bash shell找到你创建的脚本文件?shell会通过PATH环境变量来查找命令。PATH环境变量被设置成只在一组目录中查找命令。


1[njust@njust tutorials]$ echo $PATH
2/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/njust/.local/bin:/home/njust/bin


解决方法:让shell找到脚本文件,有两个方法:a.将shell脚本文件所处的目录添加到PATH环境变量中;

b.在命令行中使用绝对或相对的路径来引用shell脚本文件(常用);

由于你还没有执行文件的权限,这是由于umask变量被设置为022,因此系统创建的文件只有读写权限。使用下面的命令赋予文件有可执行权限。


1chmod u+x demo

为了引用当前目录下的文件,可以在shell中使用单点操作符.。正式执行脚本demo如下所示:


1./demo


3.显示消息


在echo命令后加上一个字符串,该命令就会显示出这个文本字符串。默认情况下,不需要使用引号将需要显示的字符串包含起来。


1[njust@njust tutorials]$ echo hello world
2hello world


当字符串中含有单引号或双引号时,可以使用双引号或单引号(注意叙述的顺序)包含该字符串。


1[njust@njust tutorials]$ echo "Let's see if this'll work"
2Let's see if this'll work

echo命令可以添加到shell脚本中任何需要显示额外信息的地方

当需要把字符串和命令输出显示在同一行时,可以使用带参数n的echo命令,如下所示:


1#!/bin/bash
2
3echo -n "The time and date are: "
4date
5
6# 结果
7The time and date are: 2020年 03月 11日 星期三 23:07:03 CST

4.使用变量


变量可以将临时信息存储在shell脚本中,便于和shell中其他的命令一起使用。环境变量:shell维护一组环境变量,用来记录特定的系统信息。可以使用set命令来显示一份完整的当前环境变量列表在脚本中,可以在环境变量名称前加上美元符号$从而来使用这些变量


1#!/bin/bash
 2
 3# print information about logger
 4
 5echo "User info for userid: $USER"
 6echo UID: $UID
 7echo HOME: $HOME
 8
 9# 结果
10User info for userid: njust
11UID: 1000
12HOME: /home/njust


注意:echo命令中的环境变量会在脚本运行时替换成当前值,只要脚本在引号中出现美元符,它就会以为你在引用一个变量,因此在表示真实美元的含义时,需要在$符号前加\转义字符。


1#!/bin/bash 
2
3echo "The cost of the item is \$5."


此外,还可以通过${变量名}的形式引用变量,变量名两侧的{}通常用于帮助识别美元符后的变量名。


用户变量:除了环境变量外,shell还允许在脚本中定义和使用自己的变量。变量名使用字母、数字或下划线组成的字符串表示,长度最长不超过20个。注意:使用等号将值赋给用户自定义的变量,在变量、等号和值之间不能出现空格!!!


1var1=23  # 等号左右不能出现空格!!
2var2=demo
3var3=testing
4var4="hello shell"


shell脚本会自动决定变量值的数据类型。在脚本的整个生命周期内,shell脚本定义的变量会一直存在,在shell脚本结束时会被删除。用户变量也可以通过$引用


1#!/bin/bash
 2
 3days=10
 4guest="curry"
 5echo "$guest checked in $days days ago"
 6
 7days=5
 8guest="durant"
 9echo "$guest cheked in $days days ago"
10
11# 结果
12curry checked in 10 days ago
13durant cheked in 5 days ago


变量每次引用时,都会输出当前赋给它的值。引用一个变量时需要使用美元符号$,引用一个变量var1给另一个变量var2进行赋值时,被赋值的变量不要使用$。对var1忘记使用$号,就会使var2的赋值行变成普通的字符串。


1#!/bin/bash
 2
 3var1=10
 4var2=$var1  # 在赋值语句中使用var1变量的值时,必须使用$符号
 5echo The resulting value is $var2
 6
 7# 结果 
 8The resulting value is 10
 9
10var2=var1;  # 错误的代表案例,输出结果是普通字符串
11echo The resulting value is $var2
12
13# 错误结果 
14The resulting value is var1


命令替换:shell最有用的特性之一是从命令输出中提取出信息,并将其赋值给变量。将命令的输出赋值给变量后,就可以在脚本中使用了。有两种方法可以将命令输出赋值给变量:  

 

a.反引号字符`    

 b.$()格式


命令替换允许你将shell命令的输出赋值给变量,具体如下所示:


1#!/bin/bash
 2
 3testing=`date`
 4test=$(date)
 5echo The date and time are: $testing
 6echo The date and time are: $test
 7
 8# 结果
 9The date and time are: 2020年 03月 12日 星期四 09:11:38 CST
10The date and time are: 2020年 03月 12日 星期四 09:11:38 CST

实例:通过命令替换获得当前日期并用它来生成唯一的文件名。


1#!/bin/bash
2
3# copy the /usr/bin/directory listing to a log file
4
5today=$(date +%y%m%d)  # +%y%m%d格式是告诉date命令将日期显示为两位数的年月日数字组合
6ls /usr/bin -al > log.$today
7
8# 结果
9生成log.200312日志文件


命令替换会创建一个子shell来运行对应的命令,由该子shell所执行命令是无法使用脚本中所创建的变量。在命令行中使用路径./运行命令时,也会创建子shell;在运行命令时不加入路径,就不会创建子shell。


5.重定向输入和输出


重定向目的:想要保存某个命令的输出而不仅仅是让结果输出在屏幕上。输出重定向:最基本的重定向是将命令的输出发送在一个文件中。格式如下:


1具体命令 > 输出文件名


实例如下:


1[njust@njust tutorials]$ date > test6
2[njust@njust tutorials]$ cat test6
32020年 03月 12日 星期四 09:40:09 CST


如果输出文件已经存在,重定向操作符会用新的文件数据覆盖已有文件


1[njust@njust tutorials]$ who > test6
2[njust@njust tutorials]$ cat test6
3njust    :0           2020-03-11 22:28 (:0)
4njust    pts/0        2020-03-12 08:39 (192.168.0.107)
5njust    pts/1        2020-03-12 08:41 (:0)


有时候,你并不想覆盖原始文件中的内容,而是想将命令的输出追加到已有文件中。这种情况下,可以用>>来追加数据


1[njust@njust tutorials]$ date >> test6
2[njust@njust tutorials]$ cat test6
3njust    :0           2020-03-11 22:28 (:0)
4njust    pts/0        2020-03-12 08:39 (192.168.0.107)
5njust    pts/1        2020-03-12 08:41 (:0)
62020年 03月 12日 星期四 09:43:41 CST


输入重定向:输入重定向将文件的内容重定向到命令,而不是将命令输出重定向到文件。输入重定向的格式:


1具体命令 < 输入文件


具体实例:wc命令可以统计文件中的数据,默认情况下会输出3个值。


1[njust@njust tutorials]$ wc < test6
24  21 186  # 从左到右分别表示文本的行数、文本的词数、文本的字节数


内联输入重定向:<<无需使用文件进行重定向,只需要在命令行中指定输入重定向的数据即可。注意:必须指定一个文本标记来划分输入数据的起始和结尾。任何字符串都可以作为文本标记,但数据的起始和结尾文本标记必须一致。格式如下所示:


1具体命令 >> EOF
2data
3EOF


在命令行中使用内联输入重定向时,shell会用PS2变量中定义的次提示符来提示用户输入数据。


1[njust@njust tutorials]$ wc << EOF
2> test string 1  # >表示的就是次提示符
3> test string 2
4> test string 3
5> EOF
63  9 42


6.管道


管道的目的:一个命令的输出作为另一个命令的输入。

管道被放在命令之间,将一个命令的输出重定向到另一个命令中。基本格式如下:


1命令1 | 命令2


管道串器的两个命令不是依次执行的,Linux系统实际上会同时运行这两个命令,在系统内部将它们连接起来。在第一个命令产生输出的同时,输出会被立即送个第二个命令。数据传输不会用的任何中间文件或缓冲区。


可以在一条命令中使用任意多条管道。可以持续地将命令的输出通过管道传给其他命令来细化操作。如下例所示:


1rpm -qa | sort | more  # 先生成已安装包的列表,再排序,最后再用more显示
2
3# 如果想更精致点,可以搭配使用重定向和管道将输出保存到文件中
4rpm -qa | sort > rpm.list


管道最流行的用法之一就是将产生的大量输出通过管道传给more命令,一般与ls命令结合使用


7.执行数学运算


在shell中有两个途径进行数学运算          

 a.expr命令            b.使用方括号


expr命令允许在命令行中处理数学表达式,但特别笨拙。许多expr命令操作符在shell中另有含义,当它们出现在expr命令中时,会得到一些诡异的结果。对那些容易被shell错误解释的字符,需要使用转义字符。


1[njust@njust tutorials]$ expr 5 * 2
2expr: 语法错误
3[njust@njust tutorials]$ expr 5 \* 2
410


在shell脚本中expr命令也同样复杂,如下所示:


1#!/bin/bash
2
3var1=10
4var2=20
5var3=$(expr $var2 / $var1)  # 要将一个数学表达式的结果赋值给一个变量var3,也需要借助命令替换。
6echo The result is $var3
7
8# 结果
9The result is 2

在bash中,在将一个数学运算结果赋给一个变量时,可以使用美元符和[]将整个表达式圈起来


1[njust@njust tutorials]$ var1=$[1+34]
2[njust@njust tutorials]$ echo $var1
335

用方括号执行shell运算比用expr命令方便很多,在shell脚本中也能看出。


1#!/bin/bash
 2
 3var1=10
 4var2=20
 5
 6var3=`expr $var2 / $var1`
 7echo the result is $var3
 8
 9var1=100
10var2=200
11var3=45
12
13var4=$[$var1 * ($var3 - $var2)]
14echo final result is $var4
15# 结果
16the result is 2
17final result is -15500


bash shell数学运算符只支持整数运算,这是一个巨大的限制。


1#!/bin/bash
2
3var1=100
4var2=45
5var3=$[$var1 / $var2]
6echo The final result is $var3
7
8# 结果
9The final result is 2


浮点数运算的解决方案:使用内建的bash计算器bc。bash计算器允许在命令行中输入浮点表达式,然后解释并计算该表达式,返回结果。浮动运算是由内建变量scale控制的,这个值设置为你需要保留的小数点后几位。


1[njust@njust ~]$ bc -q  # -q参数表示不显示欢迎信息
23.44 /5
30
4scale=4
53.44 / 5
6.6880
7quit


bash计算器还支持变量,如下所示:


1bc -q  
2var1=10
3var1*4
440
5var2=var1 / 5
6print var2
72
8quit


在脚本中使用bc:可以使用命令替换运行bc命令,并将输出赋值给一个变量。基本格式如下:


1变量名=$(echo "可选项; 表达式" | bc)


实例:在脚本中使用bc,如下所示:


1#!/bin/bash
2
3var1=$(echo "scale=4; 3.44/5" | bc)
4echo $var1
5.6880


上述方法适用于较短的运算,但有时候涉及更多的数字。需要进行大量的运算,在一个命令行中列出多个表达式就会麻烦。解决方法:使用内联输入重定向,它允许你直接在命令行中重定向数据。基本格式为:


1变量名=$(bc << EOF
2可选项
3语句
4表达式
5EOF)


在bash计算器中创建的变量只在bash计算器中有效,不能在shell脚本中使用。


1#!/bin/bash
 2
 3var1=10.46
 4var2=43.67
 5var3=33.2
 6var4=71
 7
 8var5=$(bc << EOF
 9scale=4
10a1 = ($var1 * $var2)
11b1 = ($var3 * $var4)
12a1 + b1
13EOF
14)
15echo final result is $var5
16# 结果
17final result is 2813.9882


8.退出脚本



shell中运行的每个命令都使用退出状态码,shell告诉它已经运行完毕。退出状态码是一个0到255的整数值,在命令结束时由命令传给shell,可以捕捉这个值在脚本中使用。Linux专门提供了变量$?来保存上一个已执行命令的退出状态码。对于需要进行检查的命令,必须在其运行完毕后立即查看或使用$?变量。


1[njust@njust tutorials]$ date
22020年 03月 12日 星期四 10:39:19 CST
3[njust@njust tutorials]$ echo $?
40


Linux退出状态码如下:


10           命令成功结束
21           一般性未知错误
32           不适合的shell命令
4126         命令不可执行
5127         没找到命令
6128         无效的退出参数
7130         通过CTRL+C终止的命令

exit命令:默认情况下,shell脚本会以脚本中最后一个命令的退出状态码退出。用户可以改变这种默认行为,返回自己的状态码。eixt命令允许在脚本结束时指定一个退出状态码


1#!/bin/bash
 2
 3var1=10
 4var2=30
 5var3=$[$var1 + $var2]
 6echo The answer is $var3
 7exit 5
 8
 9# 结果
10The answer is 40
11echo $?
125
13
14# 也可以在exit命令的参数中使用变量
15exit $var3
16
17echo $?
1840
19
20# 注意:退出状态码最大为255,超过最大的255后,会通过取模运算得到最后的结果即实际值 % 256 = 最结果
21var1=10
22var2=30
23var3=$[$var1 * $var2]
24echo The answer is $var3
25exit $var3
26
27echo $?
2844


9.相关资料


[1] https://github.com/cdlwhm1217096231/Linux/tree/master/Shell%E8%84%9A%E6%9C%AC%E7%BC%96%E7%A8%8B

相关文章
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
1月前
|
Shell
一个用于添加/删除定时任务的shell脚本
一个用于添加/删除定时任务的shell脚本
85 1
|
2月前
|
Shell Linux
Linux shell编程学习笔记30:打造彩色的选项菜单
Linux shell编程学习笔记30:打造彩色的选项菜单
|
25天前
|
Shell Linux 测试技术
6种方法打造出色的Shell脚本
6种方法打造出色的Shell脚本
48 2
6种方法打造出色的Shell脚本
|
11天前
|
XML JSON 监控
Shell脚本要点和难点以及具体应用和优缺点介绍
Shell脚本在系统管理和自动化任务中扮演着重要角色。尽管存在调试困难、可读性差等问题,但其简洁高效、易于学习和强大的功能使其在许多场景中不可或缺。通过掌握Shell脚本的基本语法、常用命令和函数,并了解其优缺点,开发者可以编写出高效的脚本来完成各种任务,提高工作效率。希望本文能为您在Shell脚本编写和应用中提供有价值的参考和指导。
33 1
|
16天前
|
Ubuntu Shell 开发工具
ubuntu/debian shell 脚本自动配置 gitea git 仓库
这是一个自动配置 Gitea Git 仓库的 Shell 脚本,支持 Ubuntu 20+ 和 Debian 12+ 系统。脚本会创建必要的目录、下载并安装 Gitea,创建 Gitea 用户和服务,确保 Gitea 在系统启动时自动运行。用户可以选择从官方或小绿叶技术博客下载安装包。
37 2
|
30天前
|
监控 网络协议 Shell
ip和ip网段攻击拦截系统-绿叶结界防火墙系统shell脚本
这是一个名为“小绿叶技术博客扫段攻击拦截系统”的Bash脚本,用于监控和拦截TCP攻击。通过抓取网络数据包监控可疑IP,并利用iptables和firewalld防火墙规则对这些IP进行拦截。同时,该系统能够查询数据库中的白名单,确保合法IP不受影响。此外,它还具备日志记录功能,以便于后续分析和审计。
49 6
|
26天前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
1月前
|
Shell
Shell编程(下)
Shell编程(下)
92 1
|
1月前
|
Shell Linux Windows
Shell编程(上)
Shell编程(上)
41 1
下一篇
无影云桌面