shell脚本语言的学习笔记

shell脚本语言的学习笔记

1. shell 概述

shell 通过提示您输入,向操作系统解释该输入,然后处理来自操作系统的任何结果输出,简单来说shell就是一个用户跟操作系统之间的一个命令解释器。

shell 本质上是linux命令,一条一条命令组合在一起,实现某一个目的,就变成了shell脚本。它从一定程度上,减轻了工作量,提高了工作效率。

  • 命令从广义上是用户向系统内核发出的控制信号请求,是与之交互的文本流
  • shell 命令是一个命令行解释器,将用户命令解析为操作系统所能理解的指令,是先用户与操作系统的交互
  • shell 脚本是集成了若干个命令并集合了控制语句之后的集合体,交给shell;批量执行

shell是一种脚本语言。我们只需要使用任意文本编辑器,按照语法编写相应程序,增加可执行权限,即可在安装shell 命令解释器的环境下执行。

脚本:本质是一个文件,文件里面存放的是特定格式的指令,系统可以使用脚本解释器 翻译或解析指令并执行(它不需要编译)。

shell 既是应用程序,又是一种脚本语言(应用程序 解析 脚本语言)。

shell 命令解析器:

查看自己linux 系统的默认解析:echo $SHELL

查看结果:/bin/bash

编写shell脚本的时候,最前面要加上一行:#!/bin/bash,因为linux 里面不仅仅只有bash一个解析器,还有其它的,它们之间的语法会有一些不同,所以最好加上这一句话,告诉系统要用这个解析器。

常见的shell 有哪些

​ Bourne Shell(/usr/bin/sh 或 /bin/sh)

​ Bourne Again Shell (/bin/bash)

​ C Shell (/usr/bin/csh)

​ K Shell (/usr/bin/ksh)

​ Shell for Root (/sbin/sh)

最常用的shell是Bash,也就是Bourne Again Shell。Bash 由于易用和免费,在日常生活中被广泛使用,也是大多数Linux 操作系统默认的shell 环境。

2. shell 编程注意事项

shell 编程需要注意如下

  • shell命名:Shell 脚本名称命名一般为英文、大写、小写,后缀以.sh 结尾
  • 不能使用特殊符号、空格
  • 见名知意,名称要写的一眼可以看出功能
  • shell 编程 首行需要 #!/bin/bash 开头
  • shell 脚本变量不能以数字、特殊符号开头,可以使用下滑线,但不能用破折号

1. 新建shell脚本

进入到一个你想要放脚本文件的目录。执行

# 直接新建脚本文件并进入编辑
vim test.sh

# 或者
# 先新建脚本文件,在进入编辑页面
touch test.sh
vim test.sh

2. 运行shell 脚本

一个简单的shell 脚本编写如下,并将其保存为test.sh。

#!/bin/bash

#注释
echo "helloworld"

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

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

赋予可执行权限

chmod o+x test.sh
或者粗暴一点 :  chmod 777 test.sh

有三种执行方式

  • ./test.sh 先按照文件中#!指定的解析器解析

该命令一般需要文件的可执行权限。如果#!指定的解析器不存在,才会使用系统默认的解析器

  • bash test.sh 指明先用bash 解析器解析

如果bash 不存在 才会使用默认解析器

  • . test.sh 直接使用默认解析器解析(不会执行第一行的#!指定的解析器)但是第一行还是要写的

三种执行情况:

打开终端就会有一个解析器,我们称为当前解析器

我们指定解析器的时候(使用./xxx.sh 或bash xxx.sh)时会创建一个子shell解析脚本。

3. shell 执行流程

  • 用户在命令行提示符下键入命令文本,开始与shell 进行交互
  • 之后,shell 将用户的命令或者按键转化为内核所能理解的指令
  • 控制操作系统做出响应,将命令传递到控制相关硬件设备
  • 然后,shell 将输出结构通过shell 提交给用户

4. shell命令格式

  • 通常一条命令包含三个要素:命令名称、选项、参数。命令名称是必须具备的,选项和参数都可能是可选项

  • $ command [options] argument1 argument2
    
    • 注意
      • shell提示符号中”$“表示为其他用户,”#“为超级用户
      • command命令需要严格区分大小写
      • options 参数由”-“引导
  • 一条命令的三要素由空格隔开如sudo apt-get install rxvt

  • 若将多个命令在一行书写,用分号(;)将各个命令隔开如sudo apt-get upgrade;sudo apt-get update

  • 如果一条命令不能在一行写完,在行尾使用反斜杠(\)标明该条命令还未结束

  • 使用Tab键可以补全命令,按两下Tab键可以查看同名命令或者文件;使用上下键,擦好看历史命令记录

5. shell 环境变量

shell 编程中变量分为三种,分别是系统变量、环境变量和用户变量,Shell变量名在定义时,首个字符必须为字母(a-z,A-Z),不能以数字开头,中间不能有空格,可以使用下划线(_),不能使用(-),也不能使用标点符号等。

# 简单的变量介绍
[root@keeplived_server~]# a=18
[root@keeplived_server~]# echo $a
18
系统变量
系统变量,主要是用于对参数判断和命令返回值判断时使用,系统变量详解如下:
    
$0		当前脚本的名称;
$n		当前脚本的第n个参数,n=1,2,...9;
$*		当前脚本的所有参数(不包括程序本身);
$#		当前脚本的参数个数(不包括程序本身);
$?		令或程序执行完后的状态,返回0表示执行成功;
$$		程序本身的PID号。
环境变量
环境变量,主要是在程序运行时需要设置,环境变量详解如下:
    
PATH		命令所示路径,以冒号为分割;
HOME		打印用户家目录;
SHELL		显示当前Shell类型;
USER  		打印当前用户名;
ID			打印当前用户id信息;
PWD			显示当前所在路径;
TERM		打印当前终端类型;
HOSTNAME	显示当前主机名;
PS1			定义主机命令提示符;
HISTSIZE	历史命令大小,可通过 HISTTIMEFORMAT 变量设置命令执行时间;
RANDOM		随机生成一个 032767 的整数;
HOSTNAME	主机名
用户变量
用户变量,用户变量又称为局部变量,主要用在shell 脚本内部或者临时局部使用,详解如下:
a=rivers 				       自定义变量A;
Httpd_sort=httpd-2.4.6-97.tar  自定义变量N_SOFT;
BACK_DIR=/data/backup/         自定义变量BACK_DIR;
IPaddress=10.0.0.1			   自定义变量IP1;

6. shell 注释

单行注释:以#开头作为单行注释

# 这是一个注释

多行注释:如果在开发过程中,遇到大段的代码需要临时注释起来,过一会儿又取消注释,可以将其定义为一个花括号的注释函数,也可以用多行注释

:<<EOF
注释内容...
注释内容...
注释内容...
EOF

# EOF可以换成其他符号
:<<E!
注释内容...
注释内容...
注释内容...

7. shell 编写的基本步骤

  • 建立shell文件
  • 赋予shell文件可执行程序权限(使用chmod 命令修改权限)
  • 执行shell文件(直接运行赋予权限后的二进制文件)

8. shell 中的特殊字符

1)通配符
  • shell中的通配符:用于处理查找一组名称类型相同的文件,提高效率
通配符含义实例
星号(*)匹配任意长度的字符串用file_*.txt,匹配file_zhang.txt,file_le.txt,file_wang.txt等同类型文件
问好(?)匹配一个长度的字符用file_?.txt,匹配file_1.txt,file_2.txt,file_3.txt文件
方括号([…])匹配其中指定的一个字符用file_[otr].txt,匹配file_o.txt,file_t.txt,file_r.txt特定字符
方括号([-])匹配指定的一个字符范围用file_[a-z].txt,匹配file_a.txt,file_b.txt,file_c.txt,… ,file_z.txt范围内的字符
方括号([^..]除了其中指定的单个字符,均可匹配用file_[ ^ otr ].txt,匹配除了file_o.txt,file_t.txt,file_r.txt特定字符以外的其他字符
2)管道
  • shell 中的管道可以将一些列命令连接起来,表示为第一个命令的输出将作为第二个命令的输入,通过管道传递给第二个命令,第二个命令的输出又作为第三个命令的输入,以此类推,们通常使用”|“ 符号连接命令管道

    • 通过管道和grep命令的结合,可以查看文档和终端的信息

    • ps -ef|grep tomcat
      

3. shell语法

1. shell 变量

命名变量

shell 编程中,定义变量是直接定义的,没有明确的数据类型,shell 允许用户建立变量存储数据,但是将认为赋给变量的值都解释为一串字符,如下

cout=1			# 定义变量		
name="xiaohong"	 # 定义变量
echo $cout		 # 取变量值
echo $name	     # 取变量值

shell中,英文符号"$"用于取变量值

注意:shell 编程的变量名的命名和其他语言一样,需要遵循一定的规则,规则如下

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
  • 中间不能有空格,可以使用下划线(_)
  • 不能使用标点符号
  • 不能使用bash里的关键字(可用help命令查看保留关键字)

如果在变量中使用系统命令,需要加上“ ` "符号(ESC键下方),如下所示

DATE1=`date`	
DATE2=$(date)
# 两者功能相同
使用变量

使用变量时,用英文符号"$"取变量值,对于较长的变量名,建议加上{ }花括号,帮助解释器识别变量的边界,如下:

name="test_name"
echo "My name is ${name}and you"

加上花括号时即便后面的语句不留空格,shell 也会自动识别别见,默认添加一个空格。

此外,已经定义过的变量,可以二次定义并重新被赋值覆盖上一次的变量值,这点如同其他语言

name="test_name"
echo "My name is ${name}and you"
结果:My name is test_name and you
    
name=1
echo $name
结果:1
变量类型

shell 编程中也同样存在变量类型,在运行shell时会同时存在三种变量

  • 局部变量:在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量
  • 环境变量:所有的程序,包括shell 启动的程序,都能访问环境汴玲,必要的时候shell 脚本也可以定义环境变量
  • shell变量:由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,不同类型的变量保证了shell的正常运行
变量操作

shell 中的变量,默认为可读可写类型,如果想要其只可读,如同url 一样,需要将其声明为只读类型变量(如同const),使用readonly命令,如下脚本

#!/bin/bash
Url="http://www.baidu.com"
readonly Url
Url="http://www.csnd.net"

当上述脚本执行到第4行会报错,提示/bin/sh: NAME: This variable is read only.此变量为只读变量。

如果想要删除变量,使用unset命令解除命令赋值,但是unset不能删除可读变量,如下所示

#!/bin/sh
name="xiaohong"
Url="http://www.baidu.com"
readonly Url	# 设置可读变量
unset name		# 可以被删除
unset Url		# 不可被删除
echo $name		# 不被打印出
echo $Url		# 打印出

2. shell 字符串

在shell 中字符串是shell 编程中最常用最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号。

使用单引号

str='this is a string'

使用单引号的缺点:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
  • 单引号字符串中不能出现单独一个的单引号(对单引号使用转义符也不行),但可成对出现,作为字符串拼接使用。

使用双引号

name="xiaohong"
str="please input your \"$name"\"
echo -e $str

使用双引号的好处:

  • 可以在双引号中使用变量
  • 可以在双引号中使用转义字符

由此可见,双引号较单引号而言有更强大的优势。

字符串操作
  • 获取字符串长度:在对变量进行取值时,使用“#”符号对字符串进行取值
string="abcd"
echo ${#string} # 输出 4
  • 提取子字符串:使用字符串的截取命令,用于提取部分字符串
string="this is a test"
echo ${string:2:6} # 表示下标从0开始,从第2个(包含)到第6个(包含)字符开始截取
# 输出为:`is is`
  • 查找字符串:用于查找字符的位置,输出结果为字符在字符串中所占的数据位置,如果查找多个字符,那哪个字母先出现就计算哪个,如下查找itit两个字符, t 先出现,输出为1
string="this is a test"
echo `expr index "$string" it`  # 输出 1

3. shell 数组

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

定义数组

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

# 一般定义
array _name=(value1 value2 value3 value4)

# 多级定义
array_test=(
value1
value2
value3
value4
)
   
# 赋值定义
array_text[0]=value0
array_text[1]=value1
array_text[3]=value3
...
...

三种定义形式均可。

数组操作
  • 读取属组:和读取变量名相同,使用$符号,需要加上下标名
value=${array_name[n]}
echo ${array_name[@]} # 读取所有
  • 获取数组长度:获取数组长度的方法与获取字符串长度的方法相同
# 获取数组元素的个数
length=${#array_name[@]}  # 从头到尾取
# 或者
length=${#array_name[*]}  # 取所有
# 取得数组单个元素的长度
length = ${#array_name[n]}  # 取特定

4. shell传递参数

在执行Shell脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个是参数,2 为执行脚本的第二个参数,以此类推…,脚本编写内容如下,保存为test.sh

echo "传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

执行脚本

chmod +x test.sh
./test.sh 1 2 3

输出结果为:

传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

在使用shell 传递参数的时候,常常需要用到以下的几个字符来处理参数

参数处理说明
$#传递到脚本的参数个数
$*以一个单字符串显示所有向脚本传递的参数。如”$*“ 用 ” 括起来的情况,以“$1 $2 … $n" 的形式输出所有参数。
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@与*相同,但是使用时加引号,并在引号中返回每个参数。如 “@” 用 ” 括起来的情况,以“$1" “ 2 " . . . " 2" ... " 2"..."n” 的形式输出所有参数。
$-显示Shell 使用的当前选项,与set 命令功能相同。
$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

eg:

echo "传递参数实例!";
echo "第一个参数为:$1";

echo "参数个数为:$#";
echo "传递的参数作为一个字符串显示:$*";

结果为:

传递参数实例!
第一个参数为:1
参数个数为:3
传递的参数作为一个字符串显示:1 2 3

5. shell 运算符

shell运算符种类

与其他编程语言相同的是,shell 同样支持多种运算符:

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 逻辑运算符
  • 字符串运算符
  • 文件测试运算符

shell 想要使用这些运算符,需要结合其他命令和工具来使用(因为shell中不支持简单的数学运算)

如使用算数运算符就需要搭配的常用的工具有两种

  • awk
  • expr(使用频繁)

运算规则注意点:

  • 表达式和运算符之间必须要有空格,例如 3+2 是不对的,必须写成 3 + 2
  • 完整的表达式要被两个 " ` " 包含(在ESC键下面那个键)

eg:

#!/bin/bash
val=`expr 3 + 2`
echo "两数之和为:$val"

执行脚本后,输出结果为:

两数之和为 : 5
算数运算符

shell 支持的常用的如下表,eg变量a 为10,变量b 为20

运算符说明举例
+加法expr $a + $b 结果为30
-减法expr $a - $b结果为-10
*乘法expr $a \* $b 结果为200
/除法expr $b / $a 结果为2
%取余expr $b % $a 结果为0
=赋值a=$b 将变量b的值赋给a
==相等。用于比较两个数字,相同则返回 true[ $a == $b ]返回false
!=不相等。用于比较两个数字,不相同则返回 true[ $a != $b ] 返回true

需要注意的点:

  • 在windows 系统中乘号(*) 前边必须加反斜杠(\)才能实现乘法运算;
关系运算符

shell 中的关系运算符和其他编程语言不同,shell 中使用特殊的字符表示 关系运算符,并且只支持数字,不支持字符串,除非字符串是数字,下表为常用关系运算符,同样指定a为10,b为20

运算符说明举例
-eq检测两个数是否相等,相同返回 true[ $a -eq $b ] 返回 false
-ne检测两个数是否不相等,不想等返回true[ $a -ne $b ] 返回 true
-gt检测左边的数是否大于右边的,如果是,则返回 true[ $a -gt $b ] 返回 false
-lt检测左边的数是否小于右边的,如果是,则返回true[ $a -lt $b ] 返回 true
-ge检测左边的数是否大于等于右边的,如果是,则返回true[ $a -ge $b ] 返回 false
-le检测左边的数是否小于等于右边的,如果是,则返回true[ $a -le $b ] 返回 true

eg:

#!/bin/bash

a=10
b=20

if [ $a -eq $b ]
then 
	echo "$a -eq $b : a 等于 b"
else
	echo "$a -eq $b : a 不等于 b"
fi
if [ $a -ne $b ]
then
	echo "$a -ne $b : a 不等于 b"
else
	echo "$a -ne $b : a 等于 b"
fi

执行结果如下:

10 -eq 20 : a 不等于 b
10 -ne 20 : a 不等于 b

需要注意的点

  • 运算符和数之间必须要用空格隔开
布尔运算符

shell的布尔运算符使用如下表,同样指定a 为10,b 为20

运算符说明举例
非运算,表达式为true则返回false,否则返回true[!false] 返回 true
-o或运算,有一个表达式为true 则返回true[$a -lt 20 -o $b -gt 100 ] 返回 true
-a与运算,两个表达式都为true 才返回true[ $a -lt 20 -a $b -gt 100] 返回false

eg:

#!/bin/bash
    
a=10
b=20
    
if [ $a != $b ]
then
    echo "$a != $b : a 不等于 b"
else
    echo "$a == $b : a 等于 b"
fi

执行结果如下:

10 != 20 : a 不等于 b
逻辑运算符

shell 中的逻辑运算符和其他编程语言有类似的地方,如下表。变量a为10,变量b 为 20

运算符说明举例
&&逻辑的AND[[ $a -lt 100 && &b -gt 100 ]] 返回false
||逻辑的OR[[ $a -lt 100 || $b -gt 100 ]] 返回true

eg:

#!/bin/bash

a=10
b=20
  
if [[ $a -lt 100 && &b -gt 100 ]]
then
    echo "返回 true"
else 
    echo "返回 false"
fi

执行结果如下:

返回 false

需要注意的点:

  • 这里使用两层的 [ ] 符号,将两次关系运算的结果保存在条件句中
字符串运算符

shell 中常用的字符串运算符如下。变量a 为"abc",变量b 为"efg"

运算符说明举例
=检测两个字符串是否相等,相等返回 true[ $a = $b ] 返回 false
!=检测两个字符串是否相等,不相等返回true[ $a != $b ] 返回 true
-z检测字符串长度是否为0,为0 返回true[ -z $a ] 返回false
-n检测字符串长度是否不为0,不为0 返回 true[ -n “$a” ] 返回true
$检测字符串是否为空,不为空返回true[ $a ] 返回true

eg:

#!/bin/bash
    
a="abc"
b="efg"

if [$a != $b]
then
    echo "$a != $b : a 等于 b"
else
    echo "$a != $b : a 不等于 b"
fi

执行结果如下:

abc != efg : a 不等于 b 
文件测试运算符

shell 中的文件测试运算符用于检测在类unix 系统中,文件的各种属性,如下表

操作符说明举例
-b file检测文件是否是块设备文件,如果是,则返回true[ -b $file ] 返回false
-c file检测文件是否是字符设备文件,如果是,则返回true[ -c $file ] 返回false
-d file检测文件是否是目录,如果是,则返回true[ -d $file ] 返回false
-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回true[ -f $file ] 返回false
-g file检测文件是否设置了SGID 位,如果是,则返回true[ -g $file] 返回false
-k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回true[ -k $file ] 返回false
-p file检测文件是否是有名管道,如果是,则返回true[ -p $file ] 返回false
-u file检测文件是否设置了SUID位,如果是,则返回true[ -u $file ] 返回false
-r file检测文件是否可读,如果是,则返回true[-r $file] 返回true
-w file检测文件是否可写,如果是,则返回true[-w $file ] 返回true
-x file检测文件是否可执行,如果是,则返回true[ -x $file ] 返回true
-s file检测文件是否为空(文件大小是否大于0),不为空返回true[-s $file ] 返回true
-e file检测文件(包括目录)是否存在,如果是,则返回true[-e $file ] 返回true

eg:

#!/bin/bash
    
file="/tmp/test/test.sh"
if [ -r $file ]
then
    echo "文件可读"
else
    echo "文件不可读"
fi

执行结果如下:

文件可读

4. shell 编程中的命令

1. echo 命令

echo 命令在shell中用于字符串的输出,调用的格式:

echo string
  • 显示普通的字符串

    • echo "hello world"
      
  • 显示转义字符

    • echo "\this is test\"
      
  • 显示变量

    • name="xiaoming"
      echo "name is $name"
      
  • 显示换行

    • echo -e "Right!\n" # -e 表示开启转义
      echo "this is other line"
      
  • 显示结果定向重定向至文件

    • echo "this is a test" > testfile
      
  • 显示command 命令执行结果

    • echo `date`
      

echo 命令还有其他使用规则,经常使用就可以熟练掌握

2. printf 命令

shell 中的printf命令如同C语言中一样,调用格式也大抵相同,只是有一点点不同。与echo命令打印字符串不同的是,prinf不会自动调价换行符号,可以手动添加

printf 命令的语法:

printf format-string [arguments]

参数说明:

  • format-string:格式控制字符串
  • arguments:参数列表

eg:

$ echo "hello,shell"	# 输入
hello,shell				# 输出
$ printf "hello,shell\n" # 输出
hello,shell				 # 输出

printf 命令可以较为强大的使用转义字符,shell 中常用的转义字符如下所示

序列说明
\a警告字符,通常为ASCLL的BEL字符
\b后退
\c抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f换页(formfeed)
\n换行
\r回车(Carriage return)
\t水平制表符
\v垂直制表符
\一个字面上的反斜杠字符
\ddd表示1到3位数八进制的字符。仅在格式字符串中有效
\0ddd表示1到3位的八进制值字符

3. test 命令

shell 中的 test命令用于检查某个条件是否成立,他可以进行数值、字符和文件三个方面的测试

数值测试命令表

参数说明
-eq等于则为真
-ne不等于则为真
-gt大于则为真
-ge大于等于则为真
-lt小于则为真
-le小于等于则为真

eg:

#!/bin/bash
num1=100
num2=100
if test $[num1] -eq $[num2]
then
	echo '两个数相等!'
else
	echo '两个数不相等!'
fi

执行结果如下:

两个数相等!

字符串测试表

参数说明
=等于则为真
!=不相等则为真
-z 字符串字符串的长度为零则为真
-n 字符串字符串的长度不为零则为真

eg:

#!/bin/bash
num1="hello"
num2="world"
if test $num1 = $num2
then
	echo '两个字符串相等!'
else
	echo '两个字符串不相等!'
fi

执行结果如下:

两个字符串不相等!

文件测试表

参数说明
-e 文件名如果文件存在则为真
-r 文件名如果文件存在且可读则为真
-x 文件名如果文件存在且可写则为真
-w 文件名如果文件存在且可执行则为真
-s 文件名如果文件存在且至少有一个字符则为真
-d 文件名如果文件存在且为目录则为真
-f 文件名如果文件存在且为普通文件则为真
-c 文件名如果文件存在且为字符型特殊文件则为真
-b 文件名如果文件存在且为块特殊文件则为真

eg:

#!/bin/bash
if test -e ./bash
then
	echo '文件已存在!'
else
	echo '文件不存在!'
fi

输出结果如下

文件已存在!

4. unset命令

如果想要删除变量,使用unset命令解除命令赋值,但是unset不能删除可读变量。

#!/bin/sh
name="xiaohong"
Url="http://www.baidu.com"
readonly Url	# 设置可读变量
unset name		# 可以被删除
unset Url		# 不可被删除
echo $name		# 不被打印出
echo $Url		# 打印出

5. read命令

read命令用来从键盘获取值

#!/bin/bash
num=10
echo "num=$num"
echo "请输入num的值"
read num
echo "num = $num"

执行结果如下:

num=10
请输入num的值
66
num = 66

若在一行上显示和添加提示 需要加上-p

#!/bin/bash
num=10
read -p "请输入num的值:" num
echo "num = $num"

执行结果如下:

num=10
请输入num的值:67
num = 67

5. shell 流程控制

shell 作为一种脚本语言,也有着自己的流程控制,而shell中的流程控制主要由条件、循环组成

1. if else 条件

shell 中的if else 条件具有一定的模板。其调用格式为:

  • if - then - fi

调用格式如下:

if condition
then 
	command1
	command2
	...
	commandN
fi

# 写成单行
if condition;then command1;command2;fi

如果存在不满足的条件的情况

if condition
then
	command1
	command2
	...
	commandN
else
	command
fi

在多层嵌套条件情况

if condition1
then
    command1
elif condition2
then 
    command2
else
    commandN
fi

eg:

num1=100
num2=100
if test $[num1] -eq $[num2]
then
	echo '两个数字相等!'
else
	echo '两个数字不想等!'
fi

执行结果如下:

两个数字相等!

2. case 条件

shell 中case语句为多功能选择语句,与其他语言相通的是,可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。case 语句调用格式如下:

casein
模式1)
	command1
	command2
	...
	commandN
	;;
模式2)
	command1
	command2
	...
	commandN
	;;
esac

需要注意的点

  • 取值后面需要加上in
  • 每一模式必须以右括号结束
  • 每个模式结束后使用;;符号结尾
  • 如果没有找到对应的模式。以*结尾,并跳出case
  • case需要搭配esac结尾,与C语言中的switch … case 语句类似

eg:

echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read num
case $num in
        1) echo '你选择了 1'
        ;;
        2) echo '你选择了 2'
        ;;
        3) echo '你选择了 3'
        ;;
        4) echo '你选择了 4'
        ;;
        *) echo "你没有输入 1 到 4 之间的数字"
           echo "你输入的数字是:$num"
        ;;
esac

执行结果如下:

# 1./test.sh
输入 14 之间的数字:
你输入的数字为:
4
你选择了 4
    
# 2./test.sh
输入 14 之间的数字:
你输入的数字为:
8
你没有输入 14 之间的数字
你输入的数字是:8

case中想要跳出循环有两个命令: break 和 continue

  • break 命令:允许跳出所有循环(终止执行后面所有的循环)

    • #!/bin/bash
      while :
      do
      	echo -n "输入 1 到 5 之间的数字:"
      	read num
      	case $num in
      		1|2|3|4|5) echo "你输入的数字为 $num"
      		;;
      		*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
      		    break
      		 ;;
      	esac
      done
      
    • 上述示例执行结果如下(-n 是不换行)

    • 输入 1 到 5 之间的数字:4
      你输入的数字为 4
      输入 1 到 5 之间的数字:8
      你输入的数字不是 1 到 5 之间的! 游戏结束
      
  • continue 命令:shell 中的continue 命令与break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。这一点和其他类型的语言相同

    • #!/bin/bash
      while :
      do
      	echo -n "输入 1 到 5 之间的数字:"
      	read num
      	case $num in
      		1|2|3|4|5) echo "你输入的数字为 $num"
      		;;
      		*) echo "你输入的数字不是 1 到 5 之间的!"
      			continue
      			echo "游戏结束"
      		;;
      	esac
      done
      
    • 上述示例执行结果如下

    • 输入 1 到 5 之间的数字:4
      你输入的数字为 4
      输入 1 到 5 之间的数字:6
      你输入的数字不是 1 到 5 之间的!
      输入 1 到 5 之间的数字:8
      你输入的数字不是 1 到 5 之间的!
      输入 1 到 5 之间的数字:^C
      

3. for 循环

shell 中的for循环调用格式和python中的for循环有点类似。也是有模板的:

for var in item1 item2 ... itemN
do
	command1
	command2
	...
	commandN
done

# 写成一行同时使用分号将语句分开
for var in item1 item2;do command1;command2;done

需要注意的是

  • in列表中可以包含替换、字符串和文件名等
  • in列表是可选的,如果默认不使用。将会循环使用命令行中的位置参数

eg:

for num in 1 2 3 4 5
do
	echo "The value is:$num"
done

执行结果如下

The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5

4. while 循环

shell 中的while 循环用于不断执行一系列命令,也用于从输入文件中读取数据,调用格式如下

while condition
do 
	command
done

eg:

#!/bin/bash
num=1
while(( $num<=5 ))
do 
	echo $num
	let "num++"
done

执行结果如下

1
2
3
4
5

只需要知道shell 中国while循环的格式,同样可以做到和C语言中一样,使用while循环进行判定或者判断键盘循环,甚至无限循环等,如下使用while循环读取键盘操作

echo -n "输入一个你喜欢的明星的名字:"
while read NAME
do 
	echo "你喜欢的明星是:$NAME"
done

执行结果如下

输入一个你喜欢的明星的名字:xiaohong
你喜欢的明星是:xiaohong

你喜欢的明星是:
xiaoming
你喜欢的明星是:xiaoming
^C

4. until 循环

until 循环执行一系列命令直至条件为true 时停止。until 循环与while 循环在处理方式上刚好相反。一般while 循环优于 until 循环,但在某些时候——也只是极少数情况下,until循环更加有用。until 循环调用格式:

until condition
do 
	command
done

condition一般为条件表达式,如果返回值为false,则继续执行循环体内的语句,否则跳出循环

eg:

#!/bin/bash

a=0
until [ ! $a -lt 5 ]
do
	echo $a
	a=`expr $a + 1`
done

执行结果如下:

0
1
2
3
4

6. shell 函数

1. 定义函数

linux 中的shell 同样可以定义函数,然后在函数中调用执行相关的shell 命令,完成功能,shell中的函数调用格式如下:

[ function ] funname [()]
{
	action;
	[return int;]
}

参数说明:

  • function fun () 表示有返回参数的函数(如同C语言总的有返回类型的函数(int,char等))
  • fun() 表示无返回参数的函数(类似于C语言中的void 类型函数)
  • 使用 return 可以返回参数值(一般为数值n),如果不使用,将默认以最后一条命令运行的结果作为返回值

eg:

#!/bin/bash

FunReturn(){
	echo "两个数字进行相加运算..."
	echo "输入第一个数字:"
	read num1
	echo "输入第二个数字:"
	read num2
	echo "两个数字分别是 $num1$num2"
	return $(($num1+$num2)) # 分别返回数值
}
FunReturn 	# 调用函数
echo "输入的两个数字之和为 $? " # 使用通配符获取上一条指令的返回值

执行结果如下

两个数字进行相加运算...
输入第一个数字:
5
输入第二个数字:
7
两个数字分别是 5 和 7
输入的两个数字之和为 12

需要注意的是:

  • 所有的函数在使用前必须定义,这是因为shell 解释器是顺序逐层执行的,当shell解释器发现定义的函数时,才会找到其对应的功能,进而执行。

2. 参数定义

此外想要使用shell函数传递参数时,需要在函数体的内部,通过 $n 的形式来获取参数的值,与其他语言不同的是,这不是在定义函数的时候就给定参数,而是在函数体中获取到的参数,例如,$1 表示第一个参数,$2 表示第二个参数,参数调用列表如下

参数处理说明
$#传递到脚本或函数的参数个数
$*以一个单字符串显示所有向脚本传递的参数
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@与$*相同,但是使用时加引号,并在引号中返回每个参数
$-显示shell 使用的当前选项,与set命令功能相同
$?显示最后命令的退出状态。0表示没有错误,其他任何值表示有错误

eg:

#!/bin/bash
FunParam(){
	echo "输入第一个参数 $1"
	echo "输入第二个参数 $2"
	echo "输入第十个参数 $10"
	echo "参数总数共 $# 个。"
	echo "作为一个字符串输出所有参数 $* !"
}
FunParam 1 2 3 4 5 6 7 8 9 10

执行结果如下:

输入第一个参数 1
输入第二个参数 2
输入第十个参数 10
参数总数共 10 个。
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 10 !

7. shell 重定向

输入输出重定向

  • 输入/输出重定向目的在于改变shell命令或者程序默认的标准输入/输出目标。重新定向到新的目标
  • Linux 中的默认的标注输入定义为从键盘输入,标准输出定义为从终端窗口输出
  • 用于为当前操作改变输入或者输出,迫使某人特定命令的输入或者输出来源为外部文件
重定向符号含义实例
>file将file文件重定向为输出源,新建模式ls /usr >lsoutput.txt,将ls /usr命令的执行结果,写到lsoutput.txt中去,如没有此文件将新建,若存在此文件,将覆盖
>>file将file文件重定向为输出源,追加模式ls /usr >>lsoutput.txt,将ls /usr命令的执行结果,追加到lsoutput.txt文件已有的内容之后
<file将file文件重定向为输入源wc < file1,将file1中的内容作为输入源传给wc命令
2>或&>将由命令产生的错误信息输入到文件中ls notexistfile.txt 2>err.log,使用ls命令查看一个不存在的文件名的时候,将系统错误信息提示保存在err.log文件中

命令置换

  • 命令置换就是将一个命令的输出作为另一个命令的参数,如
ls `pwd`	# 列出当前目录下的文件
echo "today is 'date'" # 写入当前时间
第1章 BashShell命令 6 1.1 Shell提示符 6 1.2 文件与目录Shell命令 7 1.2.1 更改目录命令(cd) 7 1.2.2 列表命令(ls) 7 1.2.3 操作文件命令 10 1.2.4 目录处理命令 14 1.2.5 查看文件内容命令 15 1.3 监控程序 20 1.3.1 进程查看 20 1.3.2 实时进程监控 22 1.3.3 停止进程 24 1.4 监控磁盘空间 25 1.4.1 挂载介质 25 1.4.2 使用df命令 26 1.4.3使用du命令 27 1.5 操作数据文件 28 1.5.1 数据排序(sort) 28 1.5.2 搜索数据 (grep) 30 1.5.3 压缩数据 30 1.5.4 归档数据(tar) 33 1.6 使用Linux环境变量 34 1.6.1 设置环境变量 34 1.6.2 默认的shell环境变量与path变量的设置 37 1.7 Linux文件权限 40 1.7.1 Linux安全性 40 1.7.2 使用Linux用户组 46 1.7.3 解码文件权限 47 1.7.4 修改安全设置 49 1.8 vim编辑器 52 第2章 基本脚本编译 54 2.1 创建脚本与使用变量 54 2.1.1 创建脚本 54 2.1.2 使用变量 55 2.2 重定向输入输出与数学计算 57 2.2.1 输出重定向 57 2.2.2 输入重定向 58 2.2.3 管道 58 2.2.4 数学计算 58 2.3 退出脚本 60 第3章 结构化命令 61 3.1 if语句 61 3.1.1 if-then语句 61 3.1.2 if-then-else语句 61 3.1.3 嵌套if语句 62 3.2 if条件语句 63 3.2.1 数值比较 63 3.2.2字符串比较 64 3.2.3 文件比较 65 3.2.4 复合条件检查 65 3.3 if-then的高级特征与case命令 66 3.3.1 使用双圆括号 66 3.3.2 使用双方括号 67 3.3.3 case命令 67 3.4 for命令 67 3.4.1 读取列表 68 3.4.2 读取变量与读取命令 69 3.4.3 改变字段分隔符与使用通配符读取目录 69 3.4.5 C式的for命令 70 3.5 while、until命令 71 3.5.1 使用多条测试命令 71 3.5.2 until命令与循环嵌套 72 3.6 文件数据的循环与控制循环 73 3.6.1 文件数据的循环 73 3.6.2 break命令 73 3.6.3 continue命令 75 第4章 处理用户输入与显示数据 76 4.1 命令行参数与特殊的参数变量 76 4.1.1 读取参数 76 4.1.2 读取程序名称 77 4.1.3 测试参数 77 4.1.4 参数计数 77 4.1.5 获取所有数据 78 4.2 移位与选项 79 4.2.1 移位 79 4.2.2 找出选项 79 4.2.3 使用getopt命令 81 4.2.4 更高级的getopts命令 83 4.2.4 标准化选项 84 4.3 获取用户输入 84 4.3.1 基本读取 84 4.3.2 计时 85 4.3.3 默读与文件读取 85 4.4 显示数据 86 4.4.1 标准文件描述符 86 4.4.2 重定向错误 87 4.4.3 临时重定向 88 4.4.4永久重定向 88 4.4.5 在脚本中重定向输入 89 4.5 创建自己的重定向 90 4.5.1 创建输出文件描述符 90 4.5.2 重定向文件描述符 90 4.5.3 创建输入文件描述符 91 4.5.4 创建读取/写入文件描述符 91 4.5.5 关闭文件描述符 92 4.5.6列出开发文件描述符 92 4.5.7禁止命令输出 94 4.6 使用临时文件 94 4.6.1 创建本地临时文件 94 4.6.2 在/temp中创建临时文件 95 4.6.3 创建临时目录 96 4.6.4 记录消息 96 第5章 脚本控制 97 5.1 处理信号 97 5.1.1 Linux信号回顾 97 5.1.2 生成信号 97 5.1.3捕获信号 99 5.1.4捕获脚本退出 99 5.1.4移除捕获 100 5.2 以后台模式运行脚本 100 5.3 作业控制 102 5.3.1查看作业 102 5.3.2重新启动停止的作业 103 5.4 nice与renice命令 104 5.4.1 nice命令 104 5.4.2 renice命令 104 5.5 定时运行脚本 105 5.5.1使用at命令调度作业 105 5.5.2使用batch命令调 107 5.5.3 调用定期脚本 107 5.6 从头开始 109 5.6.1在启动时启动脚本 109 5.6.2随新shell一起启动 109 第6章 创建函数 110 6.1 基本脚本函数 110 6.1.1 创建函数 110 6.1.2 使用函数 110 6.2 返回值 111 6.2.1 默认退出状态 111 6.2.2 使用return命令 111 6.2.3 使用函数输出 112 6.3 在函数中使用变量 112 6.3.1 向函数传递参数 112 6.3.2 在函数中处理变量 113 6.4 数组变量与函数 114 6.4.1 向函数传递数组 114 6.4.2从函数返回数组 115 6.5 函数递归与创建库 116 6.5.1函数递归 116 6.5.2 创建库 116 6.6 在命令行中使用函数 117 6.6.1在命令行创建函数 117 6.6.2在.bashrc文件中定义函数 117 6.7 select命令使用 119 第7章 sed、gawk介绍与正则表达式 120 7.1 sed编辑器 120 7.1.1 在命令行中定义编辑器命令 120 7.1.2 在命令行中使用多个编辑器命令 121 7.1.3 从文件读取编辑器命令 121 7.2 gawk程序 122 7.2.1 gawk命令格式 122 7.2.2 自命令行读取程序脚本 122 7.2.3 使用数据字段变量 123 7.2.4 在程序脚本中使用多个命令 124 7.2.5从文件读取程序 124 7.2.6 在处理数据之前运行脚本 125 7.2.7 在处理数据之后运行脚本 125 7.3 sed编辑器基础知识 126 7.3.1 更多替换选项 126 7.3.2 使用地址 127 7.3.3 删除行 128 7.3.4 插入和附加文本 129
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白居不易.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值