学习参考
菜鸟教程:https://www.runoob.com/linux/linux-shell.html
一.学习sheel环境
1.一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以,我使用的是centos 7
2.linux shell种类比众多,本次主要学Bash,同时Bash也是大多数Linux 系统默认的 Shell
二.创建第一个shell脚本
1.使用vi/vim 创建一个shell_test.sh文件
2.文件头#!/bin/bash或#!/bin/sh (#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序)
3.echo-控制台输出指令,在shell_test.sh输入echo “hello shell world”
4.文件提权 chmod 775 shell_test.sh
执行:./shell_test.sh
三.shell变量
1.生成变量
定义变量与python 定义变量方式一样,变量命名遵循通用的命名规则,如:不能使用数字开头,只能使用英文字母,遵循驼峰命名规则等
#!/bin/bash
variable_name="variable_test"
2.变量使用
可以直接使用$,也可加上花括号
#!/bin/bash
echo $variable_name
# 或者加上{}
echo ${variable_name}
3.变量赋值
可以使用语句给变量赋值
#!/bin/bash
# 读取指定文件夹下的所有文件,并打印
for file_name in '/home/c'/*
do echo ${file_name}
done
4.修改变量
#!/bin/bash
variable_name=1
echo ${variable_name}
variable_name=2
echo ${variable_name}
5.设置只读变量
#!/bin/bash
variable_name=12
readonly variable_name
echo ${variable_name}
variable_name=2
echo ${variable_name}
6.变量总结
运行shell时,会同时存在三种变量:
- 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
四.Shell 传递参数
(执行文件时入参)
参数 | 说明 |
---|---|
$n | n是数字,类似数组的下标(从1开始),如$1,第一个入参,$0 输出当前执行文件名 |
$# | 传递到脚本的参数个数 |
$* | 将全部入参以一个字符串打印出来 |
$@ | 与$*相反,将每个入参单独打印 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$- | 显示Shell使用的当前选项,与set命令功能相同 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
1.$n 实例:
#!/bin/bash
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
./shell_test 1 2 3 # 1 2 3 为入参
**执行结果**
Shell 传递参数实例!
执行的文件名:./sheel_test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3
2.$# 与 $* 以及 $@ 实例
#!/bin/bash
echo "Shell 传递参数实例!";
echo "参数个数为:$#";
echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done
./shell_test 1 2 3 # 1 2 3 为入参
**执行结果**
Shell 传递参数实例!
参数个数为:3
-- $* 演示 ---
1 2 3
-- $@ 演示 ---
1
2
3
3.$$ 与 $? 实例
#!/bin/bash
echo "Shell 传递参数实例!";
echo "脚本运行当前进程号:$$";
echo "执行状态:$?";
./shell_test
**执行结果**
Shell 传递参数实例!
脚本运行当前进程号:67336
执行状态:0
五.shell 字符串
1.字符串创建
字符串可以使用双引号,也使用单引号,或者不使用引号来声明
单引号字符串中的变量是无效的
#!/bin/bash
variable_name="qwe"
variable_name0="qwe ${variable_name}"
variable_name1='qwe ${variable_name}' # 单引号中的变量引用是无效的
variable_name2=qwe
2.获取字符串长度
在变量前加上#号输出字符串长度
#!/bin/bash
string="abcd"
echo ${#string[0]}
# 执行结果
4
3.切分字符串
与python 对字符串操作方式一样
#!/bin/bash
string="runoob is a great site"
echo ${string:1:4}
# 执行结果
unoo
4.查找指定字符在字符串中出现的位置
#!/bin/bash
# 查找字符 i 或 o 的位置(哪个字母先出现就计算哪个)
string="runoob is a great site"
echo `expr index "$string" io`
# 执行结果
4
六.shell 数组
1.数组创建
1.1非关联数组创建
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开,不需要声明数组长度
#!/bin/bash
shell_array0=(a b n m);
shell_array1[0]=value1;
shell_array1[1]=value2;
shell_array1[2]=value3;
1.2关联数组创建
个人理解就像是字典的创建 键是唯一的
使用declare -A指令生成数组
#!/bin/bash
# 创建关联型数组
# 方式1:创建数组时直接指定唯一的键与值对应
declare -A correlation_array0=(["key1"]="1" ["key2"]="2" ["key3"]="3" )
# 方式2:先创建数组,再指定键与值对应
declare -A correlation_array1
correlation_array1["key1"]="1"
correlation_array1["key2"]="2"
correlation_array1["key3"]="3"
2.关系型数组与非关系型数组使用
2.1取出非关系型数组元素
直接使用下标取出元素
#!/bin/bash
# 两种方式生成数组
shell_array0=(a b n m)
shell_array1[0]=value1
shell_array1[1]=value2
shell_array1[2]=value3
#读取数组
echo "shell_array0 数组的第一个元素是: ${shell_array0[0]}"
echo "shell_array1 数组的第一个元素是: ${shell_array1[0]}"
# 执行结果
shell_array0 数组的第一个元素是: a
shell_array1 数组的第一个元素是: value1
获取数组中的所有元素 以及长度(与获取字符串长度一样在数组前加"#")
#!/bin/bash
# 两种方式生成数组
shell_array0=(a b n m)
shell_array1[0]=value1
shell_array1[1]=value2
shell_array1[2]=value3
echo "读取数组"
echo "shell_array0 数组的元素为: ${shell_array0[*]}"
echo "shell_array1 数组的元素为: ${shell_array1[@]}"
echo "获取数组的长度"
echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"
echo "使用for循环取出数据"
for datas in ${shell_array0[@]}
do echo "数组元素是${datas}"
done
读取数组
shell_array0 数组的元素为: a b n m
shell_array1 数组的元素为: value1 value2 value3
获取数组的长度
数组元素个数为: 0
数组元素个数为: 0
使用for循环取出数据
数组元素是a
数组元素是b
数组元素是n
数组元素是m
2.2取出关系型数组元素
在关系型数组名前加上 “!” 号可取出关系型数组的键
数组前加"#" 获取数组长度
#!/bin/bash
# 创建关联型数组
# 方式1:创建数组时直接指定唯一的键与值对应
declare -A correlation_array0=(["key1"]="1" ["key2"]="2" ["key3"]="3" )
# 方式2:先创建数组,再指定键与值对应
declare -A correlation_array1
correlation_array1["key1"]="1"
correlation_array1["key2"]="2"
correlation_array1["key3"]="3"
# 按键取出数组的值
echo ${correlation_array1["key1"]}
# 获取数组的长度 "#" 获取数组长度
echo "数组元素个数为: ${#correlation_array1[*]}"
echo "数组元素个数为: ${#correlation_array1[@]}"
# 获取数组的建 "!" 号可取出关系型数组的键
echo "数组的键为: ${!correlation_array1[*]}"
echo "数组的键为: ${!correlation_array1[@]}"
# 取出数组的所有值
echo "数组的元素(值)为: ${correlation_array1[*]}"
echo "数组的元素(值)为: ${correlation_array1[@]}"
1
数组元素个数为: 3
数组元素个数为: 3
数组的键为: key3 key2 key1
数组的键为: key3 key2 key1
数组的元素(值)为: 3 2 1
数组的元素(值)为: 3 2 1
七.sehll 运算符
1.算术运算符
shell 运算符与各编程语言的运算符是基本一样的
举例 a=20 b=10
运算符号 | 说明 | 举例 | 运行结果 |
---|---|---|---|
+ | 加 | expr $a + $b | 30 |
- | 减 | expr $a - $b | 10 |
* | 乘 | expr $a \* $b | 200 |
/ | 除 | expr $a / $b | 0.5 |
% | 取余 | expr $a % $b | 0 |
= | 赋值 | a=$b echo ${a} | 10 (把变量 b 的值赋给 a) |
== | 相等 | [$a == $b] | false |
!= | 不相等 | $a != $b | ture |
两点注意:
1.expr 是一款表达式计算工具,运算前都要加上 expr
2.表达式和运算符之间要有空格,必须写成 2 + 2。
3.完整的表达式要被
包含,注意这个字符不是常用的单引号是反引号,在 Esc 键下边。
上表实例,结果已在表里展示,不做重复操作,只操作几种特殊的实例,下面实例程序自己代入。
#!/bin/bash
a=20
b=10
val=`expr ${a}+${b}`
echo "a + b :${val}"
# 判断是否相等
if [ $a == $b ]
then
echo "a 等于 b"
fi
# 判断是否不相等 因为结果不相等,所以不做输出
if [ $a != $b ]
then
echo "a 不等于 b"
fi
# 将变量b赋值给a
a=$b
echo ${a}
a + b :20+10
a 不等于 b
10
2.关系运算符
只支持数字,或者字符串都是数字的可使用
a=10
b=20
运算符号 | 说明 | 举例 | 运行结果 |
---|---|---|---|
-eq | 是否相等 | [ $a -eq $b ] | false |
-ne | 是否不相等 | [ $a -ne $b ] | true |
-gt | 左是否大于右 | [ $a -gt $b ] | false |
-lt | 左是否小于右 | [ $a -lt $b ] | true |
-ge | 左是否大于等于右 | [ $a -ge $b ] | false |
-le | 左是否小于等于右 | [ $a -le $b ] | true |
过于简单不做实例演示
实例:
#!/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
# 执行结果
10 -eq 20: a 不等于 b
怕你太笨,做个实例,是不是很简单
3.布尔运算符 与 逻辑运算符
3.1 布尔运算符
运算符号 | 说明 | 举例 | 运行结果 |
---|---|---|---|
! | 非运算 | [ ! false ] | ture (返回结果与判断结果相反) |
-o | 或运算 | [ $a -lt 20 -o $b -gt 100 ] | true (只要两个判断其中一个为ture 返回结果就是ture) |
-a | 与运算 | [ $a -lt 20 -a $b -gt 100 ] | false {两个判断结果都为ture 返回结果才为ture} |
口诀:
1为ture
0为false
结果相反 非
有1出1 或
全1出1 与
布尔运算是单个中括号
#!/bin/bash
a=10
b=20
if [ $a != $b ] # a不等于b返回结果是True
then
echo "$a != $b : a 不等于 b"
else
echo "$a == $b: a 等于 b"
fi
# 执行结果
10 != 20 : a 不等于 b
3.2 逻辑运算符
逻辑运算是双中括号
运算符号 | 说明 | 举例 | 运行结果 |
---|---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] | false |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] | true |
#!/bin/bash
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
# 执行结果
返回 false
返回 true
4.字符串运算符 与 文件测试运算符
4.1字符串运算符
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 |
太简单,不写实例了,参考上面的
4.2文件测试运算符
运算符号 | 说明 | 举例 | 运行结果 |
---|---|---|---|
-b file_name | 检测文件是否是块设备文件,如果是,则返回 true | [ -b $file_name ] | ture 或 false |
-c file_name | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file_name ] | ture 或 false |
-d file_name | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file_name ] | ture 或 false |
-f file_name | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file_name ] | ture 或 false |
-g file_name | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file_name ] | ture 或 false |
-k file_name | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file_name ] | ture 或 false |
-p file_name | 检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file_name ] | ture 或 false |
-u file_name | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file_name ] | ture 或 false |
-r file_name | 检测文件是否可读,如果是,则返回 true。 | [ -r $file_name ] | ture 或 false |
-w file_name | 检测文件是否可写,如果是,则返回 true。 | [ -w $file_name ] | ture 或 false |
-x file_name | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file_name ] | ture 或 false |
-s file_name | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file_name ] | ture 或 false |
-e file_name | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file_name ] | ture 或 false |
使用方法相同.只做部分示例, (这段代码没有测试成功,等测试成功再做补充)
#!/bin/bash
file_name=/home/c/lxl/Sheel_Test/shell_test.sh
if [-r ${file_name}]
then
echo "文件 ${file_name} 可读"
else
echo "文件 ${file_name} 不可读"
fi
if [-w ${file_name}]
then
echo "文件 ${file_name} 可读"
else
echo "文件 ${file_name} 不可读"
fi
八.shell中的echo / printf / test
个人觉得看下就会了,不值得写一遍,想看可以跳转到菜鸟教程
九.shell流程控制
如其他编程语言的流程控制一样包括 if elif else for while break continue
break 和 continue的用法不做单独示例,与其他编程语言中用法一样
1.if else fi
#if else 已经在上文使用过了,这里做个结构示例
if 条件
then
满足条件执行
elif 条件
then
满足条件执行
else
不满足上面条件执行
fi #
# 示例
num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
echo '两个数字相等!'
else
echo '两个数字不相等!'
fi
2.for
# for 已经在上文使用过了,这里做个结构示例
for val in (能被循环的条件)
do
执行语句
done # 结束语句
# 示例:
shell_array0=(a b n m)
echo "使用for循环取出数据"
for datas in ${shell_array0[@]}
do echo "数组元素是${datas}"
done
3.while
while 循环和其他语言基本一致
# for 已经在上文使用过了,这里做个结构示例
while 循环条件
do
执行语句
done # 结束语句
# 示例:
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
# 执行结果
1
2
3
4
5
read 读取控制台的操作
示例:
#!/bin/bash
b=5
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
if (($aNum > $b))
then
echo "你输入的数字不是 1 到 5 之间的!"
echo "游戏结束"
break
else
echo "你输入的数字是 ${aNum}"
fi
done
3.case … esac
case … esac 为多选择语句,与其他语言中的 switch … case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case … esac 语句,esac(就是 case 反过来)作为结束标记。
可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
# for 已经在上文使用过了,这里做个结构示例
while 循环条件
do
执行语句
done # 结束语句
# 示例:
#!/bin/bash
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
# 执行结果
输入 1 到 4 之间的数字:
你输入的数字为:
1
你选择了 1
十.shell 函数
1.定义一个没有入参有return 返回的函数
注:插一下return 与echo 的区别
(1).使用return返回值:
使用return返回值,只能返回1-255的整数
函数使用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回0或1;0表示成功,1表示失败
(2).使用echo返回值:
使用echo可以返回任何字符串结果
通常用于返回数据,比如一个字符串值或者列表值
#!/bin/bash
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !" # $? 这里接收调用函数的返回值
2.定义一个有入参有返回值的函数
2.1用return 返回执行结果
大于等于10的入参必须使用{}大括号加索引的方式取出
#!/bin/bash
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !" # 大于等于10的入参必须使用{}大括号加索引的方式取出
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
return $(($1+${10}))
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
echo "第一与第十数字之和为: $? !" # $? 这里接收调用函数的返回值
# 执行结果
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
第一与第十数字之和为: 35 !
2.2使用echo 接收下函数返回的执行结果
计算从 m 加到 n 的和
#!/bin/bash
function getsum(){
local sum=0 #局部变量
for((i=$1; i<=$2; i++)); do
((sum+=i))
done
echo $sum
}
echo "请输入一个数字:"
read m
echo "请再输入一个数字:"
read n
# 另一种获取返回值的方法 ``
echo "The sum is "$(getsum $m $n)
# 执行结果
请输入一个数字:
1
请再输入一个数字:
3
The sum is 6
写道这里已经有点乏了,后续的等有时间再补充
总结:
学习有点累