1、shell 简介
shell 介于内核与用户之间,负责命令的编辑,是人机交互的一个桥梁
shell 的种类
[root@yhm ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/ksh
/bin/rksh
/usr/bin/ksh
/usr/bin/rksh
种类 | 说明 |
---|---|
/bin/sh | bash的一个快捷方式 |
/bin/bash | bash是大多数Linux默认的shell,包含的功能几乎可以涵盖shell所有的功能 |
/sbin/nologin | 示非交互,不能登录操作系统 |
/bin/dash | 小巧,高效,功能相比少一些 |
/bin/csh | 具有C语言风格的一种shell,具有许多特性,但也有一些缺陷 |
bin/tcsh | csh的增强版,完全兼容csh |
2、shell 脚本
将需要执行的命令保存到文本中,按照顺序执行。它是解释型的,意味着不需要编译。
1、shell 脚本的基本写法
1、脚本第一行,#!指定解释器
#!/bin/bash 表示使用 bash 解释器解析
注意:如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题,所以可以使用 #!/bin/env 解释器
2、脚本第二部分,注释(#号)说明,对脚本的基本信息进行描述【可选】
3、脚本第三部分,脚本要实现的具体代码的内容。如:
[root@yhm bin]# vim env_bash
#!/bin/env_bash
# 以下内容是对脚本的基本信息的描述
# Name:名字
# Desc:描述 describe
# Path:存放路径
# Usage:用法
# 下面就是脚本的具体内容
a='hello'
b='world'
2、shell 脚本的执行方法
1、编写shell脚本
[root@yhm bin]# vim 1.sh
#!/bin/env bash
# 以下内容是对脚本的基本信息的描述
# Name:1.sh
# Desc:描述 describe
# Path:/bin/1.sh
# Update:2023-05-09
# 下面就是脚本的具体内容
echo 'hello java'
ehco 'hello linux'
echo 'hello shell'
2、增加可执行权限
[root@yhm bin]# chmod +x 1.sh
3、标准方式执行标准(建议)
[root@yhm bin]# pwd
/bin
[root@yhm bin]# /bin/1.sh
hello java
hello linux
hello shell
[root@yhm bin]# ./1.sh
hello java
hello linux
hello shell
注意:标准执行方式的脚本必须要有可执行的权限
4、非标准的执行方法(不建议)
1、直接在命令行指定解释器执行
[root@yhm bin]# bash 1.sh
hello java
hello linux
hello shell
[root@yhm bin]# sh 1.sh
hello java
hello linux
hello shell
2、使用 source 命令读取脚本文件,执行文件里的代码
[root@yhm bin]# source 1.sh
hello java
hello linux
hello shell
5、bash 引号
双引号“”:会把引号的内容当成整体来看待,允许通过 $ 符号引用其他变量值
单引号‘’:会把引号的内容当成整体来看待,禁止引用其他变量值,并且shell 中的特殊符号都被视为普通字符
反撇号``:和 $() 一样,引号和括号里的命令会优先执行。如果存在嵌套,反撇号不能用。
[root@yhm ~]# echo "$(hostname)"
yhm
[root@yhm ~]# echo '$(hostname)'
$(hostname)
[root@yhm ~]# echo 'hostname'
hostname
[root@yhm ~]# echo "hostname"
hostname
[root@yhm ~]# echo $(date +%Y)
2023
[root@yhm ~]# echo $(date)
2023年 05月 08日 星期一 23:26:08 EDT
[root@yhm ~]# echo $(hostname)
yhm
[root@yhm ~]# echo `echo `date +%Y``
date +%Y
[root@yhm ~]# echo `date +%Y`
2023
[root@yhm ~]# echo `echo $(date +%Y)`
2023
[root@yhm ~]# echo $(echo `date +%Y`)
2023
[root@yhm ~]# echo -e "hello\nworld\c"
hello
world[root@yhm ~]#
注:选项 -e 开启转义,\n 换行,\c:不换
3、注释
代码执行过程中,解释器会自动忽略注释。
单行注释格式:
# 这是一个注释
多行注释格式:
:<<EOF
注释内容
注释内容
注释内容
EOF
注:EOF 必须成对出现,表示注释的开始与结束,EOF也可以使用其他符号
4、变量
变量是用来临时保存数据的,该数据是可以变化的数据
1、变量定义
变量名=变量值
变量名:用来临时保存数据的
变量值:临时的可变化的数据
[root@yhm bin]# A=hello
[root@yhm bin]# echo $A
hello
[root@yhm bin]# echo ${A}
hello
[root@yhm bin]# A=world
[root@yhm bin]# echo $A
world
[root@yhm bin]# unset A
[root@yhm bin]# echo $A
2、变量的定义规则
1、变量名区分大小写
[root@yhm bin]# A=hello
[root@yhm bin]# a=world
[root@yhm bin]# echo $A
hello
[root@yhm bin]# echo $a
world
2、变量名不能有特殊符号
[root@yhm bin]# *A=hello
bash: *A=hello: 未找到命令...
[root@yhm bin]# @A=hello
bash: @A=hello: 未找到命令...
[root@yhm bin]# ?A=hello
bash: ?A=hello: 未找到命令...
注意:对于由空格的字符串给变量赋值时,要用引号引起来
[root@yhm bin]# a=hello world
bash: world: 未找到命令...
[root@yhm bin]# a="hello world"
[root@yhm bin]# a='hello world'
3、变量名不能以数字开头
[root@yhm bin]# a1=hello
[root@yhm bin]# 1a=hello
bash: 1a=hello: 未找到命令...
注意:不能以数字开头并不代表变量名中不能包含数字
4、等号两边不能有任何空格
[root@yhm bin]# a =123
bash: a: 未找到命令...
[root@yhm bin]# a= 123
bash: 123: 未找到命令...
[root@yhm bin]# a = 123
bash: a: 未找到命令...
5、变量名尽量做到见名知意
3、变量的定义方式
1、直接赋值给变量
[root@yhm bin]# a=1234567
[root@yhm bin]# echo $a
1234567
[root@yhm bin]# echo ${a:2:4}
3456
$变量名 和 ${变量名} 的异同:
相同点:都可以调用变量
不同点:${变量名} 可以只截取变量的一部分,而 $变量名 不可以
2、命令执行结果赋值给变量
[root@yhm bin]# a=`date +%Y`
[root@yhm bin]# echo $a
2023
[root@yhm bin]# a=`hostname`
[root@yhm bin]# echo $a
yhm
[root@yhm bin]# a=$(hostname)
[root@yhm bin]# echo $a
yhm
3、交互式定义变量(read)
目的:让用户自己给变量赋值,比较灵活
语法:read [选项] 变量名
常见选项:
选项 | 说明 |
---|---|
-p | 定义提示用户输入信息的语句 |
-n | 定义字符数(限制变量值的长度) |
-s | 隐藏用户输入的内容(不显示) |
-t | 定义超时时间,默认单位为秒(限制输入变量的超时时间) |
1、用户自己定义变量值
[root@yhm bin]# read name
jingxuan
[root@yhm bin]# echo $name
jingxuan
[root@yhm bin]# read -p "Input your name please:" name
Input your name please:jingxuan
[root@yhm bin]# echo $name
jingxuan
2、变量值来自文件
[root@yhm ~]# cat 1.txt
abc
[root@yhm ~]# read c < 1.txt
[root@yhm ~]# echo $c
abc
4、定义有类型的变量(declare)
目的:给变量做一些限制,固定变量的类型,比如:整型、只读
用法:declare [选项] 变量名=变量值
常用选项:
选项 | 说明 |
---|---|
-i | 定义整型变量 |
-r | 定义只读变量 |
-a | 定义普通数组,查看普通数组 |
-A | 定义关联数组,查看关联数组 |
-x | 将变量通过环境导出 |
[root@yhm ~]# declare -i A=123
[root@yhm ~]# echo $A
123
[root@yhm ~]# A=hello
[root@yhm ~]# echo $A
0
[root@yhm ~]# declare -r B=hello
[root@yhm ~]# echo $B
hello
[root@yhm ~]# B=shell
-bash: B: 只读变量
[root@yhm ~]# unset B
-bash: unset: B: 无法取消设定: 只读 variable
4、变量的分类
1、本地变量
本地变量是当前用户自定义的变量,只在当前进程中有效,其它进程及当前进程的子进程无效。
2、环境变量
环境变量不仅对当前进程有效,而且能够被子进程调用。
env:查看当前用户的环境变量
set:查询当前用户的所有变量(临时变量与环境变量)
export 变量名=变量值 或 变量名=变量值; export 变量名
1、临时将一个本地变量变成环境变量
[root@yhm ~]# export A=hello
[root@yhm ~]# env | grep A
A=hello
2、永久生效
vim /etc/profile 或 /.bash_profile
export A=hello
3、全局变量
全局所有的用户和程序都能调用和继承,新建的用户也默认能调用.相关配置文件如下:
文件名 | 说明 | 备注 |
---|---|---|
$HOME/.bashrc | 当前用户的bash信息,用户登录时读取 | 定义别名、umask、函数等 |
$HOME/.bash_profile | 当前用户的环境变量,用户登录时读取 | |
$HOME/.bash_logout | 当前用户退出当前shell时最后读取 | 定义用户退出时执行的程序等 |
/etc/bashrc | 全局的bash信息,所有用户都生效 | |
/etc/profile | 全局环境变量信息 | 系统和所有用户都生效 |
$HOME/.bash_history | 用户的历史命令 | history -w:保存历史记录,history -c:清空历史记录 |
说明:以上文件修改后,都需要重新source让其生效或者退出重新登录。
用户登录系统读取相关文件的顺序:
- /etc/profile
- $HOME/.bash_profile
- $HOME/.bashrc
- /etc/bashrc
- $HOME/.bash_logout
4、系统变量
系统变量是内置bash中的变量,shell 本身已经固定好了它的名字和作用。
内置变量 | 含义 |
---|---|
$? | 上一条命令执行后返回的状态,状态值为0表示执行正常,非0表示执行异常或错误 |
$0 | 当前执行的程序或脚本名 |
$# | 脚本后面接的参数的个数 |
$* | 脚本后面的所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开 |
$@ | 脚本后面的所有参数,参数是独立的,也是全部输出 |
$1-$9 | 脚本后面的位置参数,$1 表示第一个位置参数,依次类推 |
( 10 ) − (10)- (10)−(n) | 扩展位置参数,从第10个位置变量往后必须用{}括起来 |
$$ | 当前所在进程的进程号,如 echo $$ |
$! | 后台运行的UI后一个进程号(当前终端) |
!$ | 调用最后一条命令历史中的参数 |
[root@yhm ~]# vim 1.sh
echo "\$0 = $0"
echo "\$# = $#"
echo "\$* = $*"
echo "\$@ = $@"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"
echo "\$11 = ${11}"
echo "\$12 = ${12}"
[root@yhm ~]# bash 1.sh a b c
$0 = 1.sh
$# = 3
$* = a b c
$@ = a b c
$1 = a
$2 = b
$3 = c
$11 =
$12 =
[root@yhm ~]# vim 1.sh
#!/bin/bash
for i in "$@"
do
echo $i
done
echo "================"
for i in "$*"
do
echo $i
done
[root@yhm ~]# bash 1.sh a b c
a
b
c
================
a b c
5、简单四则运算
算术运算:默认情况下,shell 就只能支持简单的整数运算
运算内容:加(+)、减(-)、乘(*)、除(/)、取余(%)
1、四则运算的符号
表达式 | 举例 | 结果 |
---|---|---|
$(()) | echo $((1+1)) | 2 |
$[] | echo $[10-5] | 5 |
expr | expr 10/5 | 2 |
let | n=1;let n+=1 等价于 let n=n+1 | 2 |
2、i++ 和 ++i 对变量的值的影响
[root@yhm ~]# i=1
[root@yhm ~]# let i++
[root@yhm ~]# echo $i
2
[root@yhm ~]# j=1
[root@yhm ~]# let ++j
[root@yhm ~]# echo $j
2
3、i++ 和 ++i 对表达式的值的影响
[root@yhm ~]# unset i j
[root@yhm ~]# i=1;j=1
[root@yhm ~]# let x=i++
[root@yhm ~]# let y=++j
[root@yhm ~]# echo $i
2
[root@yhm ~]# echo $j
2
[root@yhm ~]# echo $x
1
[root@yhm ~]# echo $y
2
6、数组
1、数组分类
普通数组:只能使用整数作为数组索引(元素的下标)
关联数组:可以使用字符串作为数组索引(元素的下标)
2、普通数组定义
1、一次赋一个值
数组名[索引下标]=值
[root@yhm ~]# a[0]=v1
[root@yhm ~]# a[1]=v2
[root@yhm ~]# a[2]=v3
2、一次赋多个值
数组名=(值1 值2 值3 …)
[root@yhm ~]# b=(var1 var2 var3)
将文件中的每一行赋值给 c 数组
[root@yhm ~]# cat 1.txt
abc
def
hij
[root@yhm ~]# c=(`cat 1.txt`)
将 ls 查询的结果赋值给 d 数组
[root@yhm ~]# d=(`ls /home/lib`)
不同数值类型的赋值
[root@yhm ~]# e=(tom linda jack "jerry")
[root@yhm ~]# f=(1 2 3 4 "hello world" [10]=shell)
3、普通数组的读取
1、获取数组里第一个元素
[root@yhm ~]# echo ${b[0]}
var1
2、获取数组里的所有元素
[root@yhm ~]# echo ${a[*]}
v1 v2 v3
3、获取数组里所有元素个数
[root@yhm ~]# echo ${#c[*]}
3
4、获取数组元素的索引下标
[root@yhm ~]# echo ${!e[@]}
0 1 2 3
5、访问指定的元素;1代表从下标为2的元素开始获取;4代表获取后面4个元素
[root@yhm ~]# echo ${f[@]:2:4}
3 4 hello world shell
6、查看普通数组信息
[root@yhm ~]# declare -a
declare -a BASH_ARGC=()
declare -a BASH_ARGV=()
declare -a BASH_COMPLETION_VERSINFO=([0]="2" [1]="7")
declare -a BASH_LINENO=()
declare -a BASH_SOURCE=()
declare -ar BASH_VERSINFO=([0]="4" [1]="4" [2]="20" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
declare -a DIRSTACK=()
declare -a FUNCNAME
declare -a GROUPS=()
declare -a PIPESTATUS=([0]="0")
declare -ax a=([0]="v1" [1]="v2" [2]="v3")
declare -a b=([0]="var1" [1]="var2" [2]="var3")
declare -a c=([0]="abc" [1]="def" [2]="hij")
declare -a d=([0]="compat-libstdc++-33-3.2.3-72.el7.x86_64.rpm" [1]="database" [2]="elfutils-libelf-devel-0.189-2.fc39.x86_64.rpm" [3]="elfutils-libelf-devel-static-0.189-1.el8.x86_64.rpm" [4]="jdk1.8.0_151" [5]="MySQL" [6]="oracle")
declare -a e=([0]="tom" [1]="linda" [2]="jack" [3]="jerry")
declare -a f=([0]="1" [1]="2" [2]="3" [3]="4" [4]="hello world" [10]="shell")
4、关联数组定义
1、声明关联数组
[root@yhm ~]# declare -A a
[root@yhm ~]# declare -A b
[root@yhm ~]# declare -A c
2、数组赋值
1、一次赋一个值
数组名[索引]=变量值
[root@yhm ~]# a[linux]=one
[root@yhm ~]# a[java]=two
[root@yhm ~]# a[php]=three
2、一次赋多个值
[root@yhm ~]# b=([name]=tom [sno]=101 [sex]=男 [age]=18)
5、关联数组的读取
1、查看关联数组
[root@yhm ~]# declare -A
declare -A a=([java]="two" [php]="three" [linux]="one" )
declare -A b=([sno]="101" [name]="tom" [age]="18" [sex]="男" )
declare -A c
2、获取关联数组的值
[root@yhm ~]# echo ${a[linux]}
one
[root@yhm ~]# echo ${a[*]}
two three one
[root@yhm ~]# echo ${!a[*]}
java php linux
[root@yhm ~]# echo ${#c[*]}
0
7、其它变量定义
1、dirname 和 basename
dirname:取出一个目录下的目录
basename:取出一个目录下的文件
[root@yhm ~]# mkdir a
[root@yhm ~]# cd a
[root@yhm a]# touch a.txt
[root@yhm a]# A=/a/a.txt
[root@yhm a]# echo $A
/a/a.txt
[root@yhm a]# dirname $A
/a
[root@yhm a]# basename $A
a.txt
2、删除
符号 | 释义 |
---|---|
% | 从右往左去掉一个 /key/ |
%% | 从右到左最大去掉 /key/ |
# | 从左到右去掉一个 /key/ |
## | 从左到右最大去掉 /key/ |
[root@yhm a]# url=www.baidu.com
[root@yhm a]# echo ${#url}
13
[root@yhm a]# echo ${url#*.}
baidu.com
[root@yhm a]# echo ${url##*.}
com
[root@yhm a]# echo ${url%.*}
www.baidu
[root@yhm a]# echo ${url%%.*}
www
3、替换:/ 和 //
[root@yhm a]# echo ${url/b/t}
www.taidu.com
[root@yhm a]# echo ${url/w/t}
tww.baidu.com
[root@yhm a]# echo ${url//w//t}
/t/t/t.baidu.com
[root@yhm a]# echo ${url//w/t}
ttt.baidu.com
4、替代: - 、:- 、+ 、:+ 、?
1、${变量值-新的变量值} 或者 ${变量名=新的变量值}
变量没有被赋值,会使用“新的变量值”替代
变量被赋值(包括空值):不会被替代
[root@yhm ~]# echo ${abc-123}
123
[root@yhm ~]# abc=hello
[root@yhm ~]# echo ${abc-123}
hello
[root@yhm ~]# echo $abc
hello
[root@yhm ~]# b=
[root@yhm ~]# echo ${b-123}
2、${变量名:-新的变量值} 或者 ${变量名:=新的变量值}
变量没有被赋值或者赋空值:会使用“新的变量值”替代
变量被赋值:不会被替代
[root@yhm ~]# unset abc
[root@yhm ~]# echo ${abc:-123}
123
[root@yhm ~]# abc=hello
[root@yhm ~]# echo ${abc:-123}
hello
[root@yhm ~]# abc=
[root@yhm ~]# echo ${abc:-123}
123
3、${变量名+新的变量值}
变量没有被赋值:不会使用“新的变量值”替代
变量被赋过值或者被赋空值:会被替代
[root@yhm ~]# unset abc
[root@yhm ~]# echo ${abc+123}
[root@yhm ~]# abc=hello
[root@yhm ~]# echo ${abc+123}
123
[root@yhm ~]# abc=
[root@yhm ~]# echo ${abc+123}
123
4、${变量名:+新的变量值}
变量没有被赋过值或被赋空值:不会使用“新的变量值”替代
变量被赋过值:会被替代
[root@yhm ~]# echo ${abc:+123}
[root@yhm ~]# abc=hello
[root@yhm ~]# echo ${abc:+123}
123
[root@yhm ~]# abc=
[root@yhm ~]# echo ${abc:+123}
5、${变量名?新的变量值}
变量没有被赋值:提示信息
变量被赋值(包括空值):不会使用“新的变量值”替代
[root@yhm ~]# unset abc
[root@yhm ~]# echo ${abc?123}
-bash: abc: 123
[root@yhm ~]# abc=hello
[root@yhm ~]# echo ${abc?123}
hello
[root@yhm ~]# abc=
[root@yhm ~]# echo ${abc?123}