文章目录
Shell编程
Shell是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
基础语法
Shell编程的基础语法有变量、传递参数、字符串、数组、运算符、echo命令、printf命令、read命令、 test命令。
变量
在 Bash shell 中,每一个变量的值都是字符串,无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储。
定义变量
Shell 支持以下三种定义变量的方式:
#!/bin/sh --------->#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序
variable=value
variable='value'
variable="value"
#注意,赋值号=的周围不能有空格,这可能和你熟悉的大部分编程语言都不一样。
Shell 变量的命名规范和大部分编程语言都一样:
1. 变量名由数字、字母、下划线组成;
2. 必须以字母或者下划线开头;
3. 不能使用 Shell 里的关键字(通过 help 命令可以查看保留关键字)。
使用变量
使用一个定义过的变量,只要在变量名前面加美元符号$即可,如:
#!/bin/sh
train_head='huochetou'
a=houchetou
b="huochetou"
echo $train_head,$a,$b
------------------------------
huochetou,houchetou,huochetou
那么,假设现在有一个变量skill=python,要求输出“you are good at pythons job”,将其中的python用变量skill替换:
skill='python'
echo "you are good at ${skill}s job" #用花括号将变量名括起来,帮助$识别
-----------------
you are good at pythons job
推荐给所有变量加上花括号{ },这是个良好的编程习惯。
但是!!!需要注意的是,虽然双引号的单引号都可以定义变量,它们依然有区别:单引号内全部为字符串,引用的变量不能使用:
skill="java"
echo "you are good at ${skill}s job"
echo you are good at ${skill}s job
echo 'you are good at ${skill}s job'
--------------------
you are good at javas job
you are good at javas job
you are good at ${skill}s job #由此可见,单引号内不能识别变量,全部按字符串输出
命令的使用
Shell 也支持将命令的执行结果赋值给变量,常见的有以下两种方式:
#第一种方式把命令用反引号` `(位于 Esc 键的下方)包围起来,反引号和单引号非常相似,容易产生混淆,所以不推荐使用这种方式;
#第二种方式把命令用$()包围起来,区分更加明显,所以推荐使用这种方式。
variable=`Shell`
variable=$(Shell)
如:
comm=`ps`
echo $comm aaaaaaaaaa
comm2=$(ps)
echo $comm2 bbbbbbbbbb
--------------
PID TTY TIME CMD 7311 pts/4 00:00:00 bash 7960 pts/4 00:00:00 sh 7961 pts/4 00:00:00 ps aaaaaaaaaa
PID TTY TIME CMD 7311 pts/4 00:00:00 bash 7960 pts/4 00:00:00 sh 7962 pts/4 00:00:00 ps bbbbbbbbbb
只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
# readonly 只读变量 不能修改
ai_03='pretty good'
echo "$ai_03 ......." #正常变量输出
readonly ai_03 #将变量设置为只读变量
ai_03="pretty pretty good" #给变量重新赋值,尝试输出
echo "$ai_03 ......."
------------------
pretty good .......
02.sh:行24: ai_03: 只读变量 #结果可见:变量变成只读变量后,修改后无法输出
删除变量
使用 unset 命令可以删除变量。语法:
unset variable_name
变量被删除后不能再次使用;unset 命令不能删除只读变量。
比如:
# 删除变量 只读变量无法删除
unset ai_03
echo "ai_03 ....."
----------------
02.sh: 第 34 行:unset: ai_03: 无法反设定: 只读 variable
ai_03 ..... #我们看到,只读变量不能删除,依旧成功输出
===============================
# 空变量不会报错 输出一个空
unset comm2
echo "$comm2 ......."
--------------
....... #我们看到变量comm2输出一个空
传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
比如:
#!/bin/sh
# 接受文件外部传参
# 超过十的数字用括号括起来
echo "接受第一个参数$0"
echo "接受第二个参数$1"
echo "接受第三个参数$2"
echo "接受第四个参数$3"
echo "接受第五个参数$4"
echo "接受第六个参数$5"
echo "接受第Ⅶ个参数$6"
echo "接受第八个参数$7"
echo "接受第九个参数$8"
echo "接受第十个参数$9"
echo "接受第十一个参数${10}"
echo "接受第十二个参数${11}"
echo "$# 个参数"
echo "输入的参数为$@"
echo "输入的参数为$*"
外部传参,输出结果(输出的第一个参数为文件名):
[root@localhost shell_test]# sh 03.sh 2 234 5423 23535 5325 131235 235235 324 43 85 976 765 8657 5646
接受第一个参数03.sh
接受第二个参数2
接受第三个参数234
接受第四个参数5423
接受第五个参数23535
接受第六个参数5325
接受第Ⅶ个参数131235
接受第八个参数235235
接受第九个参数324
接受第十个参数43
接受第十一个参数85
接受第十二个参数976
14 个参数
输入的参数为2 234 5423 23535 5325 131235 235235 324 43 85 976 765 8657 5646
输入的参数为2 234 5423 23535 5325 131235 235235 324 43 85 976 765 8657 5646
字符串
字符串(String)就是一系列字符的组合。字符串是 Shell 编程中最常用的数据类型之一(除了数字和字符串,也没有其他类型了)。
字符串可以由单引号’ '包围,也可以由双引号" "包围,也可以不用引号。它们之间是有区别的:
-
由单引号’ '包围的字符串:
任何字符都会原样输出,在其中使用变量是无效的。字符串中不能出现单引号,即使对单引号进行转义也不行。
-
由双引号" "包围的字符串:
如果其中包含了某个变量,那么该变量会被解析(得到该变量的值),而不是原样输出。字符串中可以出现双引号,只要它被转义了就行。
-
不被引号包围的字符串:
不被引号包围的字符串中出现变量时也会被解析,这一点和双引号" "包围的字符串一样。字符串中不能出现空格,否则空格后边的字符串会作为其他变量或者命令解析。
#!/bin/sh
n=214
str1=www.aaa,com$n
str2="shell \"scripe\"$n"
str3='shell "scripe"$n'
echo $str1
echo $str2
echo $str3
echo "$str1 $str2" # 两个变量之间空格 用引号
-------------
www.aaa,com214
shell "scripe"214
shell "scripe"$n
www.aaa,com214 shell "scripe"214
获取字符串长度
在 Shell 中获取字符串长度很简单,具体方法如下:
${#string_name} #string_name 表示字符串名字
比如:
url='https://blog.csdn.net/zhangfei5354/article/details/136298293'
echo ${#url}
-------------
60
字符串截取
Shell 截取字符串通常有两种方式:从指定位置开始截取和从指定字符(子字符串)开始截取。
- 从指定位置开始截取这种方式需要两个参数:
除了指定起始位置,还需要截取长度,才能最终确定要截取的字符串。既然需要指定起始位置,那么就涉及到计数方向的问题,到底是从字符串左边开始计数,还是从字符串右边开始计数。答案是 Shell 同时支持两种计数方式。
#从左边计数
#格式:${string_name:start:length}
url='https://blog.csdn.net/zhangfei5354/article/details/136298293'
echo ${url:0:10} #从第0位开始,截取10个长度的字符
echo ${url:1} #从第1个开始,截取后面的所有字符
echo ${url:20:50}
-----------------------
https://bl
ttps://blog.csdn.net/zhangfei5354/article/details/136298293
t/zhangfei5354/article/details/136298293
#从右边计数
#格式:${string_name:0-start:length}
url='https://blog.csdn.net/zhangfei5354/article/details/136298293'
echo ${url:0-6:4}
----------
2982
注意:不管是从左边还是右边开始计数,截取方向都是从左向右!!!
- 从指定字符(子字符串)开始截取:
第二点也区分,从截取指定字符右边字符还是截取指定字符左边的字符:
# 从指定字符开始截取
# 截取右边的字符 ${string#*chars}
echo ${url#*blog}
echo ${url##*a} #找到最右边符合匹配的字符,截取其右边的字符
-----------------
.csdn.net/zhangfei5354/article/details/136298293
ils/136298293
# 截取左边的字符 ${string%chars*}
echo ${url%blog*}
echo ${url%%a*} #找到最左边符合匹配的字符,截取其左边的字符
------------
https://
https://blog.csdn.net/zh
数组
数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小。
与大部分编程语言类似,数组元素的下标由 0 开始。
定义方式
- Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下:
array_name=(value1 value2 value3 …………)
读取数组,格式:
${array_name[index]}
比如:
array=(1 2 A 4)
echo ${array[*]} #读取数组内所有的值
echo ${array[1]}
-----------
1 2 A 4
2
- 也可以用数字下表定义数组:
array1[0]=n
array1[1]=i
array1[2]=h
array1[4]=a
array1[5]=o
echo ${array1[@]}
echo ${array1[1]}
echo ${#array1[@]} #输出数组长度
----------
n i h a o
i
5
关联数组
有两种关联方式:
- 关联数组使用 declare 命令来声明,语法格式如下:
declare -A array_name
-A 选项就是用于声明一个关联数组。
关联数组的键是唯一的。
declare -A a=(['google']='www.google.com' ['taobao']='www.taobao.copm')
echo ${a['google']} #访问关联数组元素可以使用指定的键
------------------
www.google.com
- 用数字下表关联
declare -A b
b['sogou']='www.sogou.com'
b['baidu']='www.baidu.com'
b['weibo']='www.weibo.com'
echo ${b['weibo']}
-------------
www.weibo.com
获取数组的长度
获取数组长度的方法与获取字符串长度的方法相同,例如:
declare -A a=(['google']='www.google.com' ['taobao']='www.taobao.copm')
echo ${#a[*]}
#或
echo ${#a[@]}
----------------
2
2
总结
本篇介绍了Shell编程的部分基础语法:
- 变量:如何定义、使用、删除变量。
- 特别注意:单引号内全部为字符串,引用的变量不能使用。
- 传递参数:接收外界参数,超过十位的要用{}括起来
- 字符串:输出字符串、获取字符串长度、截取字符串
- 字符串的截取分为两种:
- 从指定位置开始截取:其中又区分从左边开始计数还是从右边开始,但是不管从左边还是右边,截取方向都是从左向右
- 从指定字符(子字符串)开始截取:其中也区分截取字符串左边的(%str*)还是右边的(#*str)
- 字符串的截取分为两种:
- 数组:
- 定义数组的两种方式
- 定义关联数组的两种方式
- 获取数组中的值:访问关联数组元素可以使用指定的键
- 获取数组长度