【Linux命令行与Shell脚本编程】第十一章 构建基础脚本

news/2024/11/17 4:58:52/

Linux命令行与Shell脚本编程

第十一章 构建基础脚本


文章目录

  • Linux命令行与Shell脚本编程
  • 一,构建基础脚本
    • 1,使用多个命令 ;
    • 2,创建shell脚本文件
      • 2.1,格式
      • 2.2,运行
    • 3,显示消息 echo
    • 4,使用变量
      • 4.1,环境变量 $
      • 4.2,用户自定义变量
      • 4.3,命令替换 $() ``
    • 5,重定向输入和输出
      • 5.1,输出重定向
      • 5.2,输入重定向
    • 6,管道 |
    • 7,执行数学运算 expr;[];
      • 7.1,expr命令
      • 7.2,方括号[]
      • 7.3,浮点数解决方案
        • 7.3.1,bash计算器 bc的基本用法
        • 7.3.2,在脚本中使用bc
    • 8,退出脚本 exit 0~255
      • 8.1,查看退出状态码
      • 8.2 exit命令


一,构建基础脚本

1,使用多个命令 ;

shell脚本的关键是 能够输入多个命令并处理每个命令的结果,也可以将一个命令的结果传给另一个命令。
shell可以让将多个命令串联起来,一次性执行完。
; 分割多个命令$ date ; who

2,创建shell脚本文件

2.1,格式

将shell命令放到文本文件中,
首先要用文本编辑器创建一个文件,然后在其中输入命令。
在创建shell脚本文件时,在文件的第一行指定要使用的shell,#!/bin/bash
在普通的shell脚本中, #用作注释行。
shell并不会处理shell脚本中的注释行。
shell脚本文件的第一行是个例外,#后面的惊叹号会告诉shell用哪个shell来运行脚本。
每行末尾加一个换行符。#!/bin/bash# This script displays the date and who's logged ondatewho
可以根据需要,使用分号将两个命令放在一行中,在shell脚本中,可以将命令放在独立的行中。shell会根据命令在文件中出现的顺序进行处理。

2.2,运行

路径:$ test1bash: test1: command not found让 bash shell找到你的脚本文件。shell会通过PATH环境变量来查找命令。PATH环境变量被设置为用于在其中查找命令的一系列目录。$ echo $PATH/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/user/bin $要让shell找到脚本,可以采用下列两种方法之一:·将放置shell脚本文件的目录添加到PATH环境变量中;·在命令行中使用绝对路径或相对路径来引用shell脚本文件。
权限:$ ./test1bash: ./test1: Permission denied在创建test1文件时,umask的值决定了新文件的默认权限设置。由于umask变量被设为022,因此新建的文件仅 文件属主和属组有读/写权限。(参见: 七,Linux文件权限)通过chmod命令赋予 文件属主 执行文件的权限:$ chmod u+x test1$ ./test1Mon Jun 01 15:38:19 EST 2020Christine tty2        2020-06-01 15:26

3,显示消息 echo

大多数shell命令会产生自己的输出,这些输出会显示在脚本所运行的控制台显示器上。
可以通过 echo命令后面加上字符串 来显示字符串$ echo This is a testThis is a test
默认情况下,无须使用引号将要显示的字符串划定出来。如果在字符串中使用引号,则有时会比较麻烦:$ echo Let's see if this'll workLets see if thisll work
可用单引号或双引号来划定字符串。如果在字符串中要用到某种引号,可以使用另一种引号来划定字符串:$ echo "Let's see if this'll work"Let's see if this'll work
字符串和命令输出显示在同一行中,可以使用echo命令的-n选项。echo -n "The time and date are: "$ ./test1The time and date are: Mon Jun 01 15:42:23 EST 2020

4,使用变量

在shell命令中使用其他数据来处理信息。这可以通过变量来实现。变量允许在shell脚本中临时存储信息,以便同脚本中的其他命令一起使用。

4.1,环境变量 $

用set命令显示一份完整的当前环境变量列表
在脚本中,可以在环境变量名之前加上$来引用环境变量.$ cat test2#!/bin/bash# display user information from the system.echo "User info for userid: $USER"echo UID: $UIDecho HOME: $HOME$ chmod u+x test2$ ./test2User info for userid: SamanthaUID: 1001HOME: /home/Samantha
echo命令中的环境变量会在脚本运行时被替换成当前值。
在第一个字符串中可以将 $USER系统变量放入双引号中,shell依然能够知道意图。但存在一个问题:$ echo "The cost of the item is $15"The cost of the item is 5
只要脚本在双引号中看到$,就会以为在引用变量。脚本会尝试显示变量$1的值,再显示数字5。
要显示$,必须在前面放置一个反斜线:反斜线允许shell脚本按照字面意义解释$,而不是引用变量.$ echo "The cost of the item is \$15"The cost of the item is $15
可以通过${variable}形式引用的变量。{} 通常用于帮助界定$后的变量名。

4.2,用户自定义变量

用户自定义变量的名称可以是任何由字母、数字或下划线组成的字符串,长度不能超过20个字符。变量名区分大小写.
使用等号为变量赋值。在变量、等号和值之间不能出现空格.var1=10var2=-57var3=testingvar4="still more testing"
shell脚本会以字符串形式存储所有的变量值,脚本中的各个命令可以自行决定变量值的数据类型。
shell脚本中定义的变量在脚本的整个生命周期里会一直保持着它们的值,在脚本结束时会被删除。用户自定义变量可以通过$引用$ cat test3#!/bin/bash# testing variablesdays=10guest="Katie"echo "$guest checked in $days days ago"days=5guest="Jessica"echo "$guest checked in $days days ago"$ chmod u+x test3$ ./test3Katie checked in 10 days agoJessica checked in 5 days ago
重要:引用变量值时要加$,对变量赋值时则不用加$。#!/bin/bashvalue1=10value2=value1echo The resulting value is $value2$ ./test4The resulting value is value1$ cat test4#!/bin/bashvalue1=10value2=$value1echo The resulting value is $value2$ ./test4The resulting value is 10

4.3,命令替换 $() ``

可以从命令输出中提取信息并将其赋给变量 !!!将命令输出赋给变量有两种方法:·反引号(`)·$()格式命令替换允许将shell命令的输出赋给变量,赋值号和命令替换符之间没有空格。testing=`date`testing=$(date)在脚本中通过命令替换获得当前日期并用其来生成唯一文件名:#!/bin/bashtoday=$(date +%y%m%d)ls /usr/bin -al > log.$today命令替换会创建出 子shell 来运行指定命令,这是由运行脚本的shell所生成的一个独立的shell。因此,在子shell中运行的命令无法使用脚本中的变量 !!!。
如果在命令行中使用./路径执行命令,就会创建子shell.如果不加路径,则不会创建子shell。
不过,内建的 shell命令也不会创建子shell。

5,重定向输入和输出

想要保存命令的输出 而不只是在屏幕上显示。
bash shell提供了几个运算符,可以将命令的输出重定向到其他位置(比如文件)
重定向既可用于输入,也可用于输出,例如将文件重定向,作为命令输入

5.1,输出重定向

最基本的重定向会将命令的输出发送至文件。 bash shell使用大于号(>)来实现该操作:command > outputfile
命令输出会被保存到指定的输出文件中:$ date > test6$ ls -l test6-rw-r--r--    1 user     user           29 Jun 01 16:56 test6$ cat test6Mon Jun 01 16:56:58 EDT 2020
重定向 运算符创建了文件test6(使用默认的umask设置)并将 date命令的输出重定向至该文件。
如果输出文件已存在,则重定向运算符会用新数据覆盖已有的文件.命令输出追加到已有文件中用双大于号(>>)来追加数据:$ date >> test6

5.2,输入重定向

输入重定向和输出重定向正好相反。
输入重定向会将文件的内容重定向至命令,而不是将命令输出重定向至文件输入重定向运算符是小于号(<):command < inputfile
重定向$ wc < test62      11      60
wc命令可以统计数据中的文本。在默认情况下,会输出3个值。: 文本的行数;文本的单词数;文本的字节数另外一种输入重定向的方法,称为内联输入重定向(inline input redirection)
无须使用文件进行重定向,只需在命令行中指定用于输入重定向的数据即可。内联输入重定向运算符是(<<)。除了这个符号,必须指定一个文本标记来划分输入数据的起止。任何字符串都可以作为文本标记,但在数据开始和结尾的文本标记必须一致:格式:command << markerdatamarker使用(EOF PS2环境变量中定义的次提示符)$ wc << EOF> test string 1> test string 2> test string 3 > EOF3       9      42

6,管道 |

将一个命令的输出作为另一个命令的输入。通过重定向来实现有些笨拙:$ rpm -qa > rpm.list$ sort < rpm.listabattis-cantarell-fonts-0.0.25-1.el7.noarch... ...rpm命令通过Red Hat软件包管理系统(RPM)管理系统(比如上例中的CentOS系统)中已安装的软件包。配合-qa选项使用时,会生成已安装包的列表。无须将命令输出重定向至文件,可以将其直接传给另一个命令。这个过程称为管道连接(piping).管道 符号由两个竖线构成,一个在上,一个在下。然而,其印刷体往往看起来更像是单个竖线(|)。
管道被置于命令之间,将一个命令的输出传入另一个命令中:command1 | command2
当第一个命令产生输出时,它会被立即传给第二个命令。数据传输不会用到任何中间文件或缓冲区。
管道可以串联的命令数量没有限制。可以持续地将命令输出通过管道传给其他命令来细化操作。$ rpm -qa | sort$ rpm -qa | sort | more$ rpm -qa | sort > rpm.list

7,执行数学运算 expr;[];

7.1,expr命令

在命令行中执行数学运算(笨拙,了解,不用)$ expr 1 + 56
能够识别少量算术运算符和字符串运算符     
运算符描述
ARG1ARG2
ARG1 & ARG2如果ARG1和ARG2都不为null或0,就返回ARG1;否则,返回0
ARG1 < ARG2如果ARG1小于ARG2,就返回1;否则,返回0
ARG1 <= ARG2如果ARG1小于或等于ARG2,就返回1;否则,返回0
ARG1 = ARG2如果ARG1等于ARG2,就返回1;否则,返回0
ARG1 != ARG2如果ARG1不等于ARG2,就返回1;否则,返回0
ARG1 >= ARG2如果ARG1大于或等于ARG2,就返回1;否则,返回0
ARG1 > ARG2如果ARG1大于ARG2,就返回1;否则,返回0
ARG1 + ARG2返回ARG1和ARG2之和
ARG1 - ARG2返回ARG1和ARG2之差
ARG1 * ARG2返回ARG1和ARG2之积
ARG1 / ARG2返回ARG1和ARG2之商
ARG1 % ARG2返回ARG1和ARG2之余数
STRING:REGEXP如果REGEXP模式匹配STRING,就返回该模式匹配的内容
match STRING REGEXP如果REGEXP模式匹配STRING,就返回该模式匹配的内容
substr STRING POS LENGTH返回起始位置为POS(从1开始计数)、长度为LENGTH的子串
index STRING CHARS返回CHARS在字符串STRING中所处的位置;否则,返回0
length STRING返回字符串STRING的长度
  • TOKEN |将TOKEN解释成字符串,即使TOKEN属于关键字
    (EXPRESSION) |返回EXPRESSION的值

    容易被shell错误解释的字符被传入expr命令之前,使用shell的转义字符(反斜线)对其进行转义:
    $ expr 5 * 2
    10
    要将一个数学算式的结果赋给变量,需要使用命令替换来获取expr命令
    sh中使用
    #!/bin/bash
    var1=10
    var2=20
    var3=$(expr $var2 / $var1)
    echo The result is $var3

7.2,方括号[]

为了兼容 Bourne shell,bash shell保留了expr命令,同时也提供了另一种更简单的方法来执行数学运算。
在bash中,要将数学运算结果赋给变量,可以使用 $和方括号($[ operation ])$ var1=$[1 + 5]$ echo $var16$ var2=$[$var1 * 2]$ echo $var212
用方括号来执行数学运算要比expr命令方便#!/bin/bashvar1=100var2=50var3=45var4=$[$var1 * ($var2 - $var3)]echo The final result is $var4
使用方括号执行数学运算时,无须担心shell会误解乘号或其他符号,不需要转义.仍然存在局限性,bash shell的数学运算符只支持整数运算。$ cat test8#!/bin/bashvar1=100var2=45var3=$[$var1 / $var2]echo The final result is $var3$ chmod u+x test8$ ./test8The final result is 2
! z shell(zsh)提供了完整的浮点数操作。

7.3,浮点数解决方案

最常见的做法是使用内建的bash计算器 bc

7.3.1,bash计算器 bc的基本用法

bash计算器实际上是一种编程语言,允许在命令行中输入浮点数表达式,然后解释并计算该表达式,最后返回结果
bash计算器能够识别·数字(整数和浮点数)·变量(简单变量和数组)·注释(以#或C语言中的/* */开始的行)·表达式·编程语句(比如if-then语句)·函数
通过bc命令访问 bash计算器:$ bcbc 1.06.95Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.This is free software with ABSOLUTELY NO WARRANTY.For details type 'warranty'.12 * 5.4    ##计算64.8        ##结果3.156 * (3 + 5)  ##计算25.248   ##结果quit    ##退出浮点数运算是由 内建变量 scale 控制。必须将该变量的值设置为希望在计算结果中保留的小数位数,(scale变量的默认值是0)$ bc -q3.44 / 50scale=43.44 / 5.6880quit$
-q选项 不显示 bash计算器 的 欢迎信息。

7.3.2,在脚本中使用bc

用命令替换来运行bc命令,将输出赋给变量。variable=$(echo "options; expression" | bc)
options 设置变量。需要多个变量,可以用分号来分隔。
expression 定义要通过bc执行的数学表达式。$ cat test9#!/bin/bashvar1=$(echo " scale=4; 3.44 / 5" | bc)echo The answer is $var1$ chmod u+x test9$ ./test9The answer is .6880$ cat test11#!/bin/bashvar1=20var2=3.14159var3=$(echo "scale=4; $var1 * $var1" | bc)var4=$(echo "scale=4; $var3 * $var2" | bc)echo The final result is $var4进行大量运算,使用输入重定向.
bc命令能接受输入重定向,允许将一个文件重定向到bc命令来处理。避免将表达式输入到文件中可以使用内敛输入重定向.
使用内联输入重定向,允许直接在命令行中重定向数据。在shell脚本中,可以将输出赋给一个变量:variable=$(bc << EOFoptionsstatementsexpressionsEOF)
示例: 可以在bash计算器中为变量赋值,仅在计算器中有效$ cat test12#!/bin/bashvar1=10.46var2=43.67var3=33.2var4=71var5=$(bc << EOFscale = 4a1 = ( $var1 * $var2)b1 = ($var3 * $var4)a1 + b1EOF)echo The final answer for this mess is $var5

8,退出脚本 exit 0~255

执行完最后一条命令,脚本就结束了。
shell中运行的每个命令都使用退出状态码来告诉 shell自身已经运行完毕。退出状态码是一个0~255的整数值,在命令结束运行时由其传给shell。
可以获取这个值并在脚本中使用。

8.1,查看退出状态码

Linux提供了 专门的变量 $? 来保存最后一个已执行命令的退出状态码。
对于需要进行检查的命令,必须在其运行完毕后立刻查看或使用$?变量$ dateMon Jun 01 16:01:30 EDT 2020$ echo $?0
按照惯例,对于成功结束的命令,其退出状态码是0。对于因错误而结束的命令,其退出状态码是一个正整数:$ asdfg-bash: asdfg: command not found$ echo $?127
code描述
0命令成功结束
1一般性未知错误
2不适合的shell命令
126命令无法执行
127没找到命令
128无效的退出参数
128+x与Linux信号x相关的严重错误
130通过Ctrl+C终止的命令
255正常范围之外的退出状态码

8.2 exit命令

shell脚本会以脚本中的最后一个命令的退出状态码退出$ ./test6The result is 2$ echo $?0
exit命令允许在脚本结束时指定一个退出状态码,可以使用变量作为exit命令的参数(退出状态码最大只能是255,超出会进行模256运算)$ cat test13#!/bin/bash# testing the exit statusvar1=10var2=30var3=$[ $var1 + $var2 ]echo The answer is $var3exit 5$ chmod u+x test13$ ./test13The answer is 40$ echo $?5

http://www.ppmy.cn/news/53207.html

相关文章

学成在线笔记+踩坑(8)——课程预览、提交审核,Freemarker模板引擎

导航&#xff1a; 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题_java黑马笔记 目录 1 模块需求分析 1.1 模块介绍 1.2 业务流程 1.2.1 课程预览 1.2.2 课程审核 1.2.3 课程发布 2 课程预览 2.1 需求分析…

深度学习笔记之稀疏自编码器

深度学习笔记之稀疏自编码器 引言引子&#xff1a;题目描述正确答案&#xff1a; A B C D \mathcal A \mathcal B \mathcal C \mathcal D ABCD题目解析 介绍&#xff1a;自编码器欠完备自编码器正则自编码器从先验角度解释稀疏自编码器稀疏自编码器的构建 引言 本节以一道算法…

MetaERP系统主要干什么的,华为自研ERP的路子是否可以效仿?

近日&#xff0c;华为成功研发出自主可控的MetaERP系统&#xff0c;并完成了对旧有ERP系统的替换。该系统采用全栈自主可控技术&#xff0c;基于华为欧拉操作系统、GaussDB等根技术&#xff0c;采用云原生架构、元数据多租架构、实时智能技术等&#xff0c;提高业务效率&#x…

c++标准模板(STL)(std::array)(二)

定义于头文件 <array> template< class T, std::size_t N > struct array;(C11 起) std::array 是封装固定大小数组的容器。 此容器是一个聚合类型&#xff0c;其语义等同于保有一个 C 风格数组 T[N] 作为其唯一非静态数据成员的结构体。不同于 C 风格数…

【应用部署】Java项目从开发到部署生产完整流程

文章目录 背景一、开发环境二、项目搭建2.1 Maven创建项目2.1.1 创建maven项目2.1.2 引入依赖2.1.3 maven常用命令 三、SpringBoot基础配置四、项目打包4.1 打包jar4.2 打包war4.2.1 修改项目打包为war包4.2.2 排除内嵌的tomcat&#xff0c;引入外部tomcat4.2.3 添加servlet-ap…

前端常见报错问题处理及技术点收集

一、报错问题收集 1、页面停留半小时左右不动卡死报错问题 Uncaught (in promise) TypeError: Failed to fetch dynamically imported module: http://10.233.54.161/assets/index.f8110bbc.js Promise.then (async) E main.c19f562f.js:39 f main.c19f562f.js:39 z.onClick…

基于ROS实现的机器人运动PID控制器

下面是一个基于ROS实现的机器人运动PID控制器的例子&#xff1a; 首先&#xff0c;需要定义机器人的运动控制器节点&#xff0c;例如&#xff1a; ros::NodeHandle nh; ros::Publisher cmd_vel_pub nh.advertise<geometry_msgs::Twist>("cmd_vel", 10); ros…

黑马redis实战篇-商铺缓存

目录 五、实战篇-商户查询缓存 5.1 什么是缓存 5.2 添加Redis缓存 1、不添加redis时&#xff0c;数据查询的作用模型&#xff1a; 2、添加redis时&#xff0c;数据查询的作用模型&#xff1a; 3、业务流程图&#xff1a;​编辑 4、代码实现 5、练习题 5.3 缓存更新策略…