文章目录
- [1. 总体认识](#1. 总体认识)
-
- [1.1. Shell概述](#1.1. Shell概述)
- [1.2. 第一个Shell脚本](#1.2. 第一个Shell脚本)
- [1.3. 注释](#1.3. 注释)
- [2. 变量](#2. 变量)
-
- [2.1. 定义变量](#2.1. 定义变量)
- [2.2. 使用变量](#2.2. 使用变量)
- [2.3. 只读变量](#2.3. 只读变量)
- [2.4. 删除变量](#2.4. 删除变量)
- [2.5. 变量类型](#2.5. 变量类型)
-
- [2.5.1. 字符串变量](#2.5.1. 字符串变量)
- [2.5.2. 整数变量](#2.5.2. 整数变量)
- [2.5.3. 数组变量](#2.5.3. 数组变量)
- [2.5.4. 环境变量](#2.5.4. 环境变量)
- [2.5.5. 特殊变量](#2.5.5. 特殊变量)
- [3. 输出](#3. 输出)
-
- [3.1. echo命令](#3.1. echo命令)
- [3.2. printf命令](#3.2. printf命令)
- [4. 运算符](#4. 运算符)
-
- [4.1. 运算表达式](#4.1. 运算表达式)
- [4.2. 条件表达式](#4.2. 条件表达式)
-
- [4.2.1. 关系运算符](#4.2.1. 关系运算符)
- [4.2.2. 逻辑运算符](#4.2.2. 逻辑运算符)
- [4.2.3. 字符串运算符](#4.2.3. 字符串运算符)
- [4.2.4. 文件测试运算符](#4.2.4. 文件测试运算符)
- [5. 流程控制](#5. 流程控制)
-
- [5.1. 条件语句](#5.1. 条件语句)
-
- [5.1.1. if语句](#5.1.1. if语句)
- [5.1.2. case多选择语句](#5.1.2. case多选择语句)
- [5.2. 循环语句](#5.2. 循环语句)
-
- [5.2.1. for循环](#5.2.1. for循环)
- [5.2.2. while循环](#5.2.2. while循环)
- [5.2.3. 无限循环](#5.2.3. 无限循环)
- [5.2.4. until循环](#5.2.4. until循环)
- [5.2.5. 跳出循环](#5.2.5. 跳出循环)
- [6. 函数](#6. 函数)
- [7. 输入输出重定向](#7. 输入输出重定向)
- [8. 文件包含](#8. 文件包含)
- [9. 常用shell命令](#9. 常用shell命令)
-
- [9.1. alias](#9.1. alias)
1. 总体认识
1.1. Shell概述
- Shell是一个用C语言编写的程序,这个程序提供了一个界面,用户通过这个界面可以访问操作系统内核的服务。
- Shell既是一种命令 语言,又是一种解释型的程序设计语言。
- Shell脚本(shell script),是一种为shell编写的脚本程序。
- Shell编程只要有一个能编写代码的文本编辑器 和一个能解释执行的脚本解释器就可以了。
- Linux的Shell种类众多,常用的有Bourne Shell(/usr/bin/sh或/bin/sh)、Bourne Again Shell(/bin/bash)、C Shell(/usr/bin/csh)、K Shell(/usr/bin/ksh)等等,其中Bourne Again Shell是Bourne Shell的增强版本 ,兼容性更好,且提供了更多的特性和功能。由于易用和免费,Bash是大多数Linux系统默认的Shell。
1.2. 第一个Shell脚本
-
文件名:test.sh
bash#!/bin/bash echo "Hello World!"
- shell脚本名:
*.sh
。 - 第一行使用
#!
指定解释器路径。 - 第二行
echo
语句的作用是在终端显示指定内容。
- shell脚本名:
-
运行Shell脚本
- 作为可执行程序
bashchmod +x ./test.sh # 使脚本具有执行权限 ./test.sh # 执行脚本
- 作为解释器参数
bashbash test.sh
1.3. 注释
- 单行注释:以
#
开头的行会被解释器忽略。 - 多行注释
bash
:<<EOF
Here文档中的内容不会被执行
EOF
: << delimiter
document
delimiter
:'
冒号代表空命令,后面的内容不会执行
'
2. 变量
变量是存储的数据值的名称。
2.1. 定义变量
bash
variable=value
- 注意:变量名和等号之间不能有空格。
- 变量命名要求:
- 只由字母、数字和下划线组成,不能以数字开头。
- 避免使用Shell关键字。
- 习惯上,常量的变量名通常使用大写字母
2.2. 使用变量
bash
variable=value
echo $variable
echo ${variable}
-
变量名外面的花括号是可选的,加花括号是为了帮助解释器识别变量的边界。
-
已定义的变量,可以被重新定义 。
bashvariable=value1 echo $variable variable=value2 echo $variable
2.3. 只读变量
bash
variable=value
readonly variable
2.4. 删除变量
bash
variable=value
unset variable
- 变量被删除后不能再次使用。
- unset 命令不能删除只读变量。
2.5. 变量类型
2.5.1. 字符串变量
bash
str1=hello
str2='hello'
str3="hello"
-
变量通常被视为字符串。
-
可以使用单引号 ' 或双引号 " 来定义字符串
-
单引号字符串的限制
- 单引号字符串里的任何字符都会原样输出,不能进行变量值的替换。
- 单引号字符串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
-
双引号字符串
bashname="world" str="\"Hello,$name! \"\n" echo -e $str
- 双引号字符串中可以进行值的替换。
- 双引号字符串中可以出现转义字符。
- 使用echo语句显示
\n
要添加参数-e
。
-
拼接字符串
bash
name="world"
# 使用双引号
str1="hello, "$name"!"
str2="hello, $name!" # 推荐
# 使用单引号
str3='hello, '$name'!'
- 获取字符串的长度
bash
str="hello"
echo ${#str}
echo ${#str[0]}
- 提取子字符串
bash
str="Hello, World!"
echo ${str:1:4} # 输出ello
- 查找子字符串
bash
str="Hello, World"
# 获得字符l,o第1次出现时,已经读取的字符串部分
x=${str%%[lo]*} # x的值为He
# x的长度加1即为首次出现指定字符的索引
echo $((${#x}+1)) # 输出3
2.5.2. 整数变量
bash
declare -i intvar=3
typeset -i intvar=3
这样的声明告诉Shell将intvar
视为整数,如果尝试将非整数值赋给它,Shell会尝试将其转换为整数。
2.5.3. 数组变量
-
数组变量可以在一个变量中存储多个值。
-
整数索引数组
basharray1=(1 2 3 4 5) array2=( "1" 2 "hello" ) array3[0]=value0 array3[2]=value2
- 可以不使用连续的下标,而且下标的范围没有限制。
- 索引数组元素:
${数组名[索引]}
- 获取所有元素:
${数组名[*]}
或${数组名[@]}
,两者的区别是后者常用于迭代。 - 获取数组的长度:
${#数组名[*]}
或${#数组名[@]}
- 获取数组单个元素的长度:
${#数组名[索引]}
-
关联数组
bashdeclare -A asarray asarray["name"]="John" asarray["age"]=30 declare -A site=( ["google"]="www.google.com" ["baidu"]="www.baidu.com" )
- 键可以是任意的字符串或者整数
- 键是唯一的
- 使用键访问关联数组元素:
数组名[键]
- 获得所有值:
${数组名[*]}
或${数组名[@]}
,两者的区别是后者常用于迭代。 - 获得所有键:
${!数组名[*]}
或${!数组名[@]}
,两者的区别是后者常用于迭代。 - 获得数组长度:
${#数组名[*]}
或${#数组名[@]}
2.5.4. 环境变量
-
环境变量是由操作系统或用户设置的特殊变量,用于配置Shell的行为和影响其执行环境。
-
PATH变量包含了操作系统搜索可执行文件的路径
-
将路径添加PATH
bashexport PATH=${your_path}:$PATH
- 直接在终端执行是临时设置
- 要永久设置则须写入配置文件
- 当前登陆用户配置文件:
~/.bashrc
- 所有用户的配置文件:
/etc/profile
- 写入后要重新加载:
source ${config_path}
- 当前登陆用户配置文件:
-
添加其他环境变量与PATH变量类似
2.5.5. 特殊变量
特殊变量 | 作用 |
---|---|
$0 |
脚本名称 |
$1 , $2 , ... |
脚本参数 |
$# |
传递给脚本的参数数量 |
$* |
以一个单字符串接收所有向脚本传递的参数 |
$@ |
以"$1" " 2 " ... " 2" ... " 2"..."n" 的形式接收所有参数,常用于迭代 |
$? |
上一个命令的退出状态,0表示没有错误,其他任何值表明有错误。 |
$$ |
脚本运行的当前进程ID号 |
$! |
后台运行的最后一个进程的ID号 |
$- |
显示Shell使用的当前选项,与set命令功能相同。 |
3. 输出
3.1. echo命令
- 命令格式
bash
echo string
- 显示普通字符串
bash
echo "It is a test"
echo It is a test
- 显示转义字符
bash
echo "\"It is a test\""
echo \"It is a test\"
- 显示变量
bash
# 标准输入中读取一行(不允许转义)到变量name
read -r name
echo "$name is good!"
- 显示换行
bash
echo -e "OK! \n" # -e 开启转义
echo "******"
- 显示不换行
bash
echo "OK! \n" # 原样输出\n
echo "******"
echo -e "OK! \c" # -e 开启转义,但不换行
echo "******"
- 原样输出字符串
bash
echo '$name\"'
- 显示命令执行结果
bash
echo "Date: $(date)"
3.2. printf命令
printf
命令模仿C程序库里的printf()
函数。- 命令格式
bash
printf format-string [arguments...]
- 格式化字符串参照C语言
- 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,
format-string
被重用 - 如果没有
arguments
,那么%s
用NULL
代替,%d
用0
代替 - 格式化字符串中的
%b
格式- 用于参数中存在
\n
时,输出换行。用%s
会原样输出\n
。 - 仅在
%b
格式下,\c
可以抑制(不显示)输出结果中任何结尾的换行字符,而且其后的所有内容全部忽略。用%s
会原样输出\c
。
- 用于参数中存在
4. 运算符
4.1. 运算表达式
-
运算表达式的使用
bashval=$((2 + 2)) echo "$val"
-
$((...))
中不用考虑空格的问题,变量不用加$
号。 -
支持的运算
运算符 含义 举例 +
加法 $((a + b))
-
减法 $((a - b))
*
乘法 $((a * b))
/
除法 $((a / b))
%
取余 $((a % b))
++
自增,与C++相同 $((a++))
--
自减,与C++相同 $((a--))
=
赋值,右值作为结果 $((a = b))
==
比较相等,相等为1,否则为0 $((a - b))
!=
比较不相等,不相等为1,否则为0 $((a - b))
>
比较大于,大于为1,否则为0 $((a - b))
<
比较小于,小于为1,否则为0 $((a - b))
>=
比较大于等于,大于等于为1,否则为0 $((a - b))
<=
比较小于等于,小于等于为1,否则为0 $((a - b))
-
4.2. 条件表达式
-
条件表达式的使用
basha=2 b=1 if test $a -eq $b then echo "相等" elif [ $a -ge $b ] then echo "大于" elif (($a < $b)) echo "小于" else echo "错误" fi
- 条件表达式通常用于流程控制中
- 条件判断可以使用
test 条件表达式
- 条件判断可以使用
[ 条件表达式 ]
,注意要有空格 - 条件判断可以使用
((条件表达式))
,此时可以不用考虑空格
4.2.1. 关系运算符
只支持数字,不支持字符串。
运算符 | 含义 | 举例 |
---|---|---|
-eq |
检测两个数是否相等,相等返true。 | [ $a -eq $b ] |
-ne |
检测两个数是否不相等,不相等返回true。 | [ $a -ne $b ] |
-gt |
检测两个数是否大于右边的,如果是,则返回true。 | [ $a -gt$b ] |
-lt |
检测两个数是否小于右边的,如果是,则返回true。 | [ $a -lt $b ] |
-ge |
检测两个数是否大于等于右边的,如果是,则返回true。 | [ $a -ge $b ] |
-le |
检测两个数是否小于等于右边的,如果是,则返回true。 | [ $a -le $b ] |
4.2.2. 逻辑运算符
优先级:! > && > ||
,存在短路运算。
运算符 | 含义 | 举例 |
---|---|---|
&& |
逻辑与运算 | [[ $a -lt 100 && $b -gt 15 ]] |
` | ` | |
! |
逻辑非运算 | [[ ! $a -lt 100 ]] |
4.2.3. 字符串运算符
运算符 | 含义 | 举例 |
---|---|---|
= |
检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] |
!= |
检测两个字符串是否不相等,不相等返回 true。 | [ $a != $b ] |
-z |
检测字符串长度是否为0,为0返回 true。 | [ -z $a ] |
-n |
检测字符串长度是否不为0,不为0返回 true。 | [ -n $a ] |
$ |
检测字符串是否不为空,不为空返回 true。 | [ $a ] |
4.2.4. 文件测试运算符
用于检测Unix文件的各种属性。
运算符 | 含义 | 举例 |
---|---|---|
-b |
检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] |
-c |
检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] |
-d |
检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] |
-f |
检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] |
-g |
检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] |
-k |
检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] |
-p |
检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] |
-u |
检测文件是否设置了SUID位,如果是,则返回 true。 | [ -u $file ] |
-r |
检测文件是否可读,如果是,则返回 true。 | [ -r $file ] |
-w |
检测文件是否可写,如果是,则返回 true。 | [ -w $file ] |
-x |
检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] |
-s |
检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] |
-e |
检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] |
-S |
判断某文件是否 socket。 | [ -S $file ] |
-L |
检测文件是否存在并且是一个符号链接。 | [ -L $file ] |
5. 流程控制
5.1. 条件语句
5.1.1. if语句
- 最展开的格式
bash
if 条件判断
then
命令1
命令2
...
elif 条件判断
then
命令1
命令2
...
else
命令1
命令2
...
fi
- 写成一行要加分号分隔
bash
if 条件判断; then 命令; fi
if 条件判断; then
命令1
命令2
...
fi
5.1.2. case多选择语句
bash
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
*)
command1
command2
...
commandN
;;
esac
5.2. 循环语句
5.2.1. for循环
- 最展开的格式
bash
for var in item1 item2
do
命令1
命令2
...
done
- 写成一行要加分号分隔
bash
for var in item1 item2; do 命令1; 命令2; done
5.2.2. while循环
- 一般格式
bash
while 条件判断
do
命令1
命令2
...
done
- 循环读取键盘输入
bash
while read -r site
do
echo "是的!$site 是一个好网站"
done
5.2.3. 无限循环
bash
while true
do
命令
done
5.2.4. until循环
先执行,再判断
bash
until 条件判断
do
命令
done
5.2.5. 跳出循环
break
是跳出本级循环continue
跳出本次循环
6. 函数
- 格式
bash
function funname [()]
{
action
[return int;]
}
[ function ] funname ()
{
action
[return int;]
}
- 所有函数在使用前必须定义。
- 调用函数仅使用其函数名即可。
- 返回值
- 如果不return语句,将以最后一条命令运行结果作为返回值。
- 只能返回0-255。
- 函数返回值在调用该函数后通过
$?
来获得。
- 函数参数与脚本的命令行参数相同
7. 输入输出重定向
-
文件描述符
- 0表示标准输入(STDIN)
- 1表示标准输出(STDOUT)
- 2表示标准错误输出(STDERR)
-
空设备文件nul(指向/dev/null)
-
输出重定向到文件,覆盖原文件。
bashcommand > file
-
输出以追加的方式重定向到文件
bashcommand >> file
-
合并标准输出和标准错误输出,并重定向到文件
bashcommand > file 2>&1
-
错误输出重定向到文件
bashcommand 2> file
-
将输入重定向为文件
bashcommand < file
-
Here文档:将输入重定向为两个分隔符之间的内容
bashcommand << delimiter document delimiter
-
对标准输入和标准输出都进行重定向
bashcommand < file1 > file2
-
屏蔽命令输出
bashcommand > nul command > /dev/null
8. 文件包含
bash
. filename # 注意有空格
source filename
上述语句会先执行指定shell脚本,但是保留shell脚本执行结束会清理的变量等内容
9. 常用shell命令
9.1. alias
- 用于设置指令的别名
- 语法
bash
alias [别名]="[指令名称]"
- 注意多条指令用分号分隔