shell脚本

以下内容来自:
脚本之家
c语言中文网
c语言中文网
shell 整形自增

一、shell简介

shell是Linux系统的用户界面,它提供用户与内核的一种交互方式。它接收用户输入的命令,并把它送入内核去执行,是一个命令解释器。
在这里插入图片描述

在这里插入图片描述
shell脚本就是将命令写入文本中,文本可以被执行。
脚本:本质是一个文件,文件里面存放的是 特定格式的指令,系统可以使用脚本解析器 翻译或解析 指令 并执行(它不需要编译)
shell 既是应用程序,又是一种脚本语言(应用程序 解析 脚本语言)。

二、执行方式

  • ./xxx.sh 先按照#!指定的解析器解析,如果找不到使用默认解析
  • bash xxx.sh 指定使用bash解析器解析,找不到使用默认解析
  • . xxx.sh 直接使用默认解析

三、脚本的调用形式

可以手动执行脚本或自动执行脚本。
手动:
①chmod +x xxx.sh(添加可执行权限) ./xxx.sh(执行脚本)
②source xxx.sh
……(还有其他方法)

自动执行:写到其他脚本中,利用脚本去调用。比如写道开机脚本中,开机会自动调用。

打开终端时系统自动调用:/etc/profile 或 ~/.bashrc

/etc/profile
此文件为Linux系统为每个用户设置环境变量,当用户第一次登陆时,该文件会被执行。 系统的公共环境变量在这里设置
开始自启动的程序,一般也在这里设置。

注意:错误的修改系统配置文件时,可能会导致重复输密码一直无法进入桌面的现象。
解决方法:进入终端机也就是字符界面(tty1-tty6):[Ctrl] + [Alt] + [F1] ~[F6],还原被修改的文件,重启即可。
[Ctrl] + [Alt] + [F7]返回图形界面。

~/.bashrc
用户自己的家目录中的.bashrc
登录时会自动调用,打开一个新终端时也会自动调用
这个文件一般设置与个人用户有关的环境变量 ,如交叉编译器的路径等等
在这里插入图片描述

三、shell语法

3.1、定义以开头:#!/bin/sh

#!用来声明脚本由什么shell解释,否则使用默认shell

3.2、单个”#”号代表注释当前行

shell脚本注释
<<EOF xxxxxxx EOF 能注释多行
在这里插入图片描述

3.5、变量

变量定义

Shell 变量的命名规范和大部分编程语言都一样:

  • 变量名由数字、字母、下划线组成;
  • 必须以字母或者下划线开头;
  • 不能使用 Shell 里的关键字(通过 help 命令可以查看保留关键字)。

shell支持以下3种方式定义变量:

variable=value			#普通赋值方法
variable='value'
variable="value"		#当变量的值(字符串)中包含任何空白符时,加双引号

赋值符两边不能有空格,若变量值本身包含了空格,则整个字符串都要用双引号、或单引号括起来。

双引号和单引号的区别

在双引号中会引用变量的值,而单引号只把它当字符处理。
在这里插入图片描述
在这里插入图片描述

**问题:在脚本中定义的变量,脚本结束后,变量和它的值还在,命令行“echo $变量名”可以查看。 **

变量类型

在shell中给变量赋值会默认视为字符串,不管有没有加双引号,即使你将整数或者小数赋值给它。

当然如果有需要也可以设置变量类型:
设置变量类型:typeset或declare可以设置变量类型。
比如:
typeset -i data 表示将data设置为int型。

使用变量

使用一个定义过的变量,只要在变量名前面加美元符号$即可,如:

author="严长生"
echo $author
echo ${author}

花括号{ }是可选的,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

skill="Java"
echo "I am good at ${skill}Script

如果不给 skill 变量加花括号,写成echo “I am good at $skillScript”,解释器就会把 $skillScript 当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。

推荐给所有变量加上花括号{ },这是个良好的编程习惯。

变量作用域

运行shell时,会同时存在三种变量:
1) 局部变量
局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
2) 环境变量
所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
3) shell变量
shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

shell中的一些关键字

echo: 打印

echo “xxxxx” #打印字符串
echo $变量名 #打印变量的值
例如:echo $PATH 可以打印环境变量PATH的值
在这里插入图片描述
env #打印所有的环境变量

显示结果重定向至文件

会在当前目录下创建myfile文件,并写入字符串。

echo "It is a test" > myfile

unset:变量值清除。

read: 读取键盘输入。read 变量名。读取输入的值到变量。

脚本内容:
read 从键盘读取变量的值, -p 可以在打印字符的当前行的最后输入。也可以同时读取多个值。
变量赋值demo
运行结果:
在这里插入图片描述

readonly:只读变量

3.6 预设变量

shell直接提供无需定义的变量。
预设变量
shell脚本支持从命令行传递参数,参数之间用空格隔开:
$? 命令执行后返回的状态:返回0表示成功,非0表示失败
在这里插入图片描述
在这里插入图片描述

3.7 脚本变量的特殊用法

在这里插入图片描述

系统命令调用和转义字符

调用系统命令用··(反单引号)
转义字符使用加“-e”
在这里插入图片描述
在这里插入图片描述

命令序列

“()”中由子shell执行,类似于子进程(“()”内定义的变量仅在此文件有效)
在这里插入图片描述
在这里插入图片描述
“{}”由当前shell执行
在这里插入图片描述

3.8 变量的扩展

判断变量是否存在

在这里插入图片描述

在这里插入图片描述
这里100是因为,在之前的脚本中,定义过num变量。
在这里插入图片描述
两者区别“

n

u

m

:

v

a

l

{num:-val}” 和 “

num:val{num:=val}”。
在这里插入图片描述

3.9字符串操作

计算字符串长度

string="abcd"
echo ${#string} #输出 4

提取子串

string="alibaba is a great company"
echo ${string:1:4} #输出liba

拼接字符串

your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

查找字符串

string="alibaba is a great company"
echo `expr index "$string" is`
text="read phy addr: 0x1f  reg: 0x1f   value : 0x0"
str="value : "
value=${text#*$str}

#打印value的值
echo "$value"
0x0

替换字符

string="123123"
echo ${string/3/0}			#用0替换第一个遇见的3
echo ${string//3/0}			#用0替换串中所有3

在这里插入图片描述

在这里插入图片描述

运算符

算术运算符

Bash 支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。

expr 是一款表达式计算工具,使用它能完成表达式的求值操作:
例如,两个数相加:

#!/bin/bash
val=`expr 2 + 2`
echo "Total value : $val"

两点注意:

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

在这里插入图片描述

test命令:用于测试字符串、文件状态和数值。

test命令有两种格式:
test condition 或[ condition ]
使用方括号时,要注意在条件两边加上空格。

文件测试运算符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

字符串运算符

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

关系运算符

在这里插入图片描述
在这里插入图片描述

3.11 与或非

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。

定义数组

在Shell中,用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为:

array_name=(value0 value1 value2 value3)

array_name=(
value0
value1
value2
value3
)

还可以单独定义数组的各个分量:

array_name[0]=value0
array_name[1]=value1
array_name[2]=value2

可以不使用连续的下标,而且下标的范围没有限制。

读取数组

读取数组
读取数组元素值的一般格式是:

${array_name[index]}

如:

valuen=${array_name[2]}

使用@ 或 * 可以获取数组中的所有元素,例如:

${array_name[*]}
${array_name[@]}

获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同,例如:

# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}

3.12 控制语句

if控制语句

格式一:
if [条件1]
then
  执行第一段程序
else
  执行第二段程序
fi
格式二:
if [条件1] 
then
  执行第一段程序
elif [条件2] 
then
执行第二段程序
else
  执行第三段程序
fi

注意空格

判断字符串
在这里插入图片描述
在这里插入图片描述
判断文件是否存在
在这里插入图片描述
在这里插入图片描述

case 控制语句

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

for循环语句

与c语言不同,循环的值可以时字符串
在这里插入图片描述
注意空格
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
扫描当前文件
在这里插入图片描述
在这里插入图片描述

while控制语句

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用while与read组合,循环读取键盘输入:

while read FILM
do
    echo "Yeah! great film the $FILM"
done

until

在这里插入图片描述
在这里插入图片描述

break、continue

在这里插入图片描述
在嵌套循环中,break 命令后面还可以跟一个整数,表示跳出第几层循环。例如:

break n

表示跳出第 n 层循环。
同样,continue 后面也可以跟一个数字,表示跳出第几层循环。

函数

所有函数在使用前必须定义,必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用
在这里插入图片描述
在这里插入图片描述
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…

#!/bin/bash
funWithParam(){
    echo "The value of the first parameter is $1 !"
    echo "The value of the second parameter is $2 !"
    echo "The value of the tenth parameter is $10 !"
    echo "The value of the tenth parameter is ${10} !"
    echo "The value of the eleventh parameter is ${11} !"
    echo "The amount of the parameters is $# !"  # 参数个数
    echo "The string of the parameters is $* !"  # 传递给函数的所有参数
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

注意,

10

10 不能获取第十个参数,获取第十个参数需要

10{10}。当n>=10时,需要使用${n}来获取参数。

求最值
在这里插入图片描述
函数分文件
在这里插入图片描述
fun.sh
在这里插入图片描述
24_sh.sh
在这里插入图片描述

输出重定向

命令的输出不仅可以是显示器,还可以很容易的转移向到文件,这被称为输出重定向。

命令输出重定向的语法为:

command > file

这样,输出到显示器的内容就可以被重定向到文件。

例如,下面的命令在显示器上不会看到任何输出:

who > users

打开 users 文件,可以看到下面的内容:

$ cat users
oko         tty01   Sep 12 07:30
ai          tty15   Sep 12 13:32
ruth        tty21   Sep 12 10:10
pat         tty24   Sep 12 13:07
steve       tty25   Sep 12 13:03

输出重定向会覆盖文件内容,请看下面的例子

$ echo line 1 > users
$ cat users
line 1
$

如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾,例如:

$ echo line 2 >> users
$ cat users
line 1
line 2
$

输入重定向

和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:

command < file

这样,本来需要从键盘获取输入的命令会转移到文件读取内容。

注意:输出重定向是大于号(>),输入重定向是小于号(<)。

例如,计算 users 文件中的行数,可以使用下面的命令:

$ wc -l users
2 users
$

也可以将输入重定向到 users 文件:

$ wc -l < users
2
$

重定向深入了解

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

shell文件包含

像其他语言一样,Shell 也可以包含外部脚本,将外部脚本的内容合并到当前脚本。
Shell 中包含脚本可以使用:

. filename
或
source filename