shell
// 内容大量来源于黑马程序员
1. 脚本第一行 ,魔法字符 #! 指定解释器【 必写 】
#!/bin/bash` 表示以下内容使用bash解释器解析
注1
2. 脚本增加可执行权限 (意思就是如果你的文件是灰色,仅仅代表个普通文件,使用之后,将变成了绿色,代表可执行文件。 在linux里不同的颜色代表不同的文件)
[root@MissHou shell01]# chmod +x mytest.sh
----------------------------------
3. 标准方式执行脚本
[root@MissHou shell01]# /shell01/mytest.sh
或者
[root@MissHou shell01]# ./mytest.sh
4. 非标准的执行方法(不建议)
4.1 直接在命令行指定解释器执行
[root@MissHou shell01]# bash mytest.sh
[root@MissHou shell01]# sh mytest.sh
[root@MissHou shell01]# bash -x mytest.sh
-x:一般用于排错,查看脚本的执行过程
-n:用来查看脚本的语法是否有问题
4.2 使用`source`命令读取脚本文件,执行文件里的代码
[root@MissHou shell01]# source mytest.sh
------------------------------------
5. 定义变量(区分大小写; 不能有特殊符号; 不能以数字开头; 对于有空格的字符串给变量赋值时,要用引号引起来)
[root@MissHou ~]# A=hello 定义变量A
[root@MissHou ~]# echo $A 调用变量A,要给钱的,不是人民币是美元"$"
hello
[root@MissHou ~]# echo ${A} 还可以这样调用,不管你的姿势多优雅,总之要给钱
hello
[root@MissHou ~]# A=world 因为是变量所以可以变,移情别恋是常事
[root@MissHou ~]# echo $A 不管你是谁,只要调用就要给钱
world
[root@MissHou ~]# unset A 不跟你玩了,取消变量
[root@MissHou ~]# echo $A 从此,我单身了,你可以给我介绍任何人
6. [root@MissHou ~]# A=1234567
[root@MissHou ~]# echo $A
1234567
[root@MissHou ~]# echo ${A:2:4} 表示从A变量中第3个字符开始截取,截取4个字符
3456
说明:
$变量名 和 ${变量名}的异同
相同点:都可以调用变量
不同点:${变量名}可以只截取变量的一部分,而$变量名不可以
7. 交互式定义变量(read)
| -p | 定义提示用户的信息 |
| -n | 定义字符数(限制变量值的长度) |
| -s | 不显示(不显示用户输入的内容) |
| -t | 定义超时时间,默认单位为秒(限制用户输入变量值的超时时间) |
用法1:用户自己定义变量值
[root@MissHou ~]# read name
harry
[root@MissHou ~]# echo $name
harry
[root@MissHou ~]# read -p "Input your name:" name
Input your name:tom
[root@MissHou ~]# echo $name
tom
用法2:变量值来自文件
[root@MissHou ~]# cat 1.txt
10.1.1.1 255.255.255.0
[root@MissHou ~]# read ip mask < 1.txt
[root@MissHou ~]# echo $ip
10.1.1.1
[root@MissHou ~]# echo $mask
255.255.255.0
8. 定义有限制的变量(declare)
| -i | 将变量看成整数 | declare -i A=123 |
| -r | 定义只读变量 | declare -r B=hello |
| -a | 定义普通数组;查看普通数组 | |
| -A | 定义关联数组;查看关联数组 | |
| -x | 将变量通过环境导出 | declare -x AAA=123456 等于 export AAA=123456 |
[root@MissHou ~]# declare -i A=123
[root@MissHou ~]# echo $A
123
[root@MissHou ~]# A=hello
[root@MissHou ~]# echo $A
0
[root@MissHou ~]# declare -r B=hello
[root@MissHou ~]# echo $B
hello
[root@MissHou ~]# B=world
-bash: B: readonly variable
[root@MissHou ~]# unset B
-bash: unset: B: cannot unset: readonly variable
9. 变量的分类
㈠ 本地变量 :当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。
㈡ 环境变量 :当前进程有效,并且能够被 子进程 调用。
env查看当前用户的环境变量
set查询当前用户的所有变量(临时变量与环境变量)
export 变量名=变量值 或者 变量名=变量值;export 变量名
㈢ 全局变量 :全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用.
解读相关配置文件
| 文件名 | 说明 | 备注 |
| -------------------- | -------------------------------------- | ---------------------------------------------------------- |
| $HOME/.bashrc | 当前用户的bash信息,用户 登录 时读取 | 定义别名、umask、函数等 |
| $HOME/.bash_profile | 当前用户的环境变量,用户 登录 时读取 | |
| $HOME/.bash_logout | 当前用户 退出 当前shell时最后读取 | 定义用户退出时执行的程序等 |
| /etc/bashrc | 全局的bash信息,所有用户都生效 | |
| /etc/profile | 全局环境变量信息 | 系统和所有用户都生效 |
| \$HOME/.bash_history | 用户的历史命令 | history -w 保存历史记录 history -c 清空历史记录 |
说明: 以上文件修改后,都需要重新 source 让其生效或者退出重新登录。
用户登录 系统 读取 相关 文件的顺序
1. /etc/profile
2. $HOME/.bash_profile
3. $HOME/.bashrc
4. /etc/bashrc
5. $HOME/.bash_logout
㈣ 系统变量 (内置bash中变量) : shell本身已经固定好了它的名字和作用.
| 内置变量 | 含义 |
| ------------ | ------------------------------------------------------------ |
| $? | 上一条命令执行后返回的状态;状态值为0表示执行正常,非0表示执行异常或错误 |
| $0 | 当前执行的程序或脚本名 |
| $# | 脚本后面接的参数的个数 |
| $* | 脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开 |
| $@ | 脚本后面所有参数,参数是独立的,也是全部输出 |
| $1~$9 | 脚本后面的位置参数,$1表示第1个位置参数,依次类推 |
| ${10}~${n} | 扩展位置参数,第10个位置变量必须用{}大括号括起来(2位数字以上扩起来) |
| $$ | 当前所在进程的进程号,如`echo $$` |
| $! | 后台运行的最后一个进程号 (当前终端) |
| !$ | 调用最后一条命令历史中的参数 |
10. $* :表示将变量看成一个整体
$@ :表示变量是独立的
#!/bin/bash
for i in "$@"
do
echo $i
done
echo "======我是分割线======="
for i in "$*"
do
echo $i
done
[root@MissHou ~]# bash 3.sh a b c
a
b
c
======我是分割线=======
a b c
------------------------------------------------------------------------------
11. 定义数组
㈠ 数组分类
- 普通数组:只能使用整数作为数组索引(元素的下标)
- 关联数组:可以使用字符串作为数组索引(元素的下标)
㈡ 普通数组定义
一次赋予一个值
数组名[索引下标]=值
array[0]=v1
array[1]=v2
array[2]=v3
array[3]=v4
一次赋予多个值
数组名=(值1 值2 值3 ...)
array=(var1 var2 var3 var4)
array1=(`cat /etc/passwd`) 将文件中每一行赋值给array1数组, 注意,语句中的顿号不要少, 比如cat前面
array2=(`ls /root`)
array3=(harry amy jack "Miss Hou")
array4=(1 2 3 4 "hello world" [10]=linux)
```
㈢ 数组的读取
declare -a 查看所有的数组
echo ${array[0]} 获取数组里第一个元素
echo ${array[*]} 获取数组里的所有元素
echo ${#array[*]} 获取数组里所有元素个数
echo ${!array[@]} 获取数组元素的索引下标
echo ${array[@]:1:2} 访问指定的元素;1代表从下标为1的元素开始获取;2代表获取后面几个元素
㈣ 关联数组定义
①首先声明关联数组 declare -A asso_array1
② 数组赋值
一次赋一个值
asso_array1[linux]=one
asso_array1[java]=two
一次赋多个值
asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="Miss Hou")
③获取关联数组值
echo ${asso_array1[linux]}
-------------------------------------------------------------------------------------------------------------------------------
12. 操作变量
变量"内容"的删除和替换
一个“%”代表从右往左去掉一个/key/
两个“%%”代表从右往左最大去掉/key/
一个“#”代表从左往右去掉一个/key/
两个“##”代表从左往右最大去掉/key/
举例说明:
# url=www.taobao.com
# echo ${#url} 获取变量的长度
# echo ${url#*.}
# echo ${url##*.}
# echo ${url%.*}
# echo ${url%%.*}
13. 替代: - 和 :- +和:+ 等
内容过多,参考
https://www.cnblogs.com/zhaosunwei/p/6831529.html
------------------------------------------------------------------
14. 条件判断语法结构
格式1: test 条件表达式
格式2: [ 条件表达式 ] 注意两边都有空格,下面格式一样
格式3: [[ 条件表达式 ]] 支持正则 =~
㈠ 判断文件类型
| 判断参数 | 含义 |
| -------- | -------------------------------------------- |
| -e | 判断文件是否存在(任何类型文件) |
| -f | 判断文件是否存在并且是一个普通文件 |
| -d | 判断文件是否存在并且是一个目录 |
| -L | 判断文件是否存在并且是一个软连接文件 |
| -b | 判断文件是否存在并且是一个块设备文件 |
| -S | 判断文件是否存在并且是一个套接字文件 |
| -c | 判断文件是否存在并且是一个字符设备文件 |
| -p | 判断文件是否存在并且是一个命名管道文件 |
| -s | 判断文件是否存在并且是一个非空文件(有内容) |
test -e file 只要文件存在条件为真
[ -d /shell01/dir1 ] 判断目录是否存在,存在条件为真
[ ! -d /shell01/dir1 ] 判断目录是否存在,不存在条件为真
[[ -f /shell01/1.sh ]] 判断文件是否存在,并且是一个普通的文件
㈡ 判断文件权限
| 判断参数 | 含义 |
| -------- | -------------------------- |
| -r | 当前用户对其是否可读 |
| -w | 当前用户对其是否可写 |
| -x | 当前用户对其是否可执行 |
| -u | 是否有suid,高级权限冒险位 |
| -g | 是否sgid,高级权限强制位 |
| -k | 是否有t位,高级权限粘滞位 |
㈢ 判断文件新旧
说明:这里的新旧指的是 文件的修改时间。
| 判断参数 | 含义 |
| ---------------- | ------------------------------------------------------------ |
| file1 -nt file2 | 比较file1是否比file2新 |
| file1 -ot file2 | 比较file1是否比file2旧 |
| file1 -ef file2 | 比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode |
㈣ 判断整数
| 判断参数 | 含义 |
| -------- | -------- |
| -eq | 相等 |
| -ne | 不等 |
| -gt | 大于 |
| -lt | 小于 |
| -ge | 大于等于 |
| -le | 小于等于 |
㈤ 判断字符串
| 判断参数 | 含义 |
| ------------------ | ----------------------------------------------- |
| -z | 判断是否为==空==字符串,字符串长度为0则成立 |
| -n | 判断是否为==非空==字符串,字符串长度不为0则成立 |
| string1 = string2 | 判断字符串是否相等 |
| string1 != string2 | 判断字符串是否相不等 |
㈥ ==多重条件判断==
| 判断符号 | 含义 | 举例 |
| ---------- | ------ | ----------------------------------------------------- |
| -a 和 && | 逻辑与 | [ 1 -eq 1 -a 1 -ne 0 ] [ 1 -eq 1 ] && [ 1 -ne 0 ] |
| -o 和 \|\| | 逻辑或 | [ 1 -eq 1 -o 1 -ne 1 ] |
15. 其他:
注意:在(( ))中,=表示赋值;==表示判断
[root@server ~]# ((1==2));echo $?
注意:双引号引起来,看作一个整体;= 和 == 在 [ 字符串 ] 比较中都表示判断
[root@server ~]# a='hello world';b=world
[root@server ~]# [ $a = $b ];echo $?
[root@server ~]# [ "$a" = "$b" ];echo $?
[root@server ~]# [ "$a" != "$b" ];echo $?
[root@server ~]# [ "$a" == "$b" ];echo $?
-------------------------------------------------------------------------------------------------
17. 流程控制语句
if [ condition ];then
command
command
fi
---------
if [ condition ];then
command1
else
command2
fi
-----------
if [ condition1 ];then
command1 结束
elif [ condition2 ];then
command2 结束
else
command3
fi
-----------------
18. 查找进程
pgrep命令:以名称为依据从运行进程队列中查找进程,并显示查找到的进程id
选项
-o:仅显示找到的最小(起始)进程号;
-n:仅显示找到的最大(结束)进程号;
-l:显示进程名称;
-P:指定父进程号;pgrep -p 4764 查看父进程下的子进程id
-g:指定进程组;
-t:指定开启进程的终端;
-u:指定进程的有效用户ID。
19. 其他
id $id &> /dev/null , 中 &> /dev/null 这条命令的意思是将标准输出和错误输出全部重定向到/dev/null中,也就是将产生的所有信息丢弃.
read -p "aaa" id
------------------------------------------------------------------------
20. for循环语句
---------------
20.1 for variable in {list}
do
command
command
…
done
----------
for variable in a b c
do
command
command
done
--------------
# for var in {1..10};do echo $var;done
----------
20.2 for variable
do
command
command
…
done
-----------
20.3 for(( expr1;expr2;expr3 ))
do
command
command
…
done
----------------
# for (( i=1;i<=5;i++))
do
echo $i
done
-----------------
21. while 表达式
do
command...
done
while [ 1 -eq 1 ] 或者 (( 1 > 2 ))
do
command
command
...
done
-------
while循环打印:
i=1
while [ $i -le 5 ]
do
echo $i
let i++
done
--------------
22. until循环
until expression [ 1 -eq 1 ] (( 1 >= 1 ))
do
command
command
...
done
------
i=1
until [ $i -gt 5 ]
do
echo $i
let i++
done
-------------------------
23. case语句
说明:pattern表示需要匹配的模式
case var in 定义变量;var代表是变量名
pattern 1) 模式1;用 | 分割多个模式,相当于or
command1 需要执行的语句
;; 两个分号代表命令结束
pattern 2)
command2
;;
pattern 3)
command3
;;
*) default,不满足以上模式,默认执行*)下面的语句
command4
;;
esac esac表示case语句结束
---------------------
例如:
#!/bin/env bash
case $1 in
start|S)
service apache start &>/dev/null && echo "apache 启动成功"
;;
stop|T)
service apache stop &>/dev/null && echo "apache 停止成功"
;;
restart|R)
service apache restart &>/dev/null && echo "apache 重启完毕"
;;
*)
echo "请输入要做的事情..."
;;
esac
---------------
25. 其他
exit 退出整个程序
break 结束当前循环,或跳出本层循环
continue 忽略本次循环剩余的代码,直接进行下一次循环
shift 使位置参数向左移动,默认移动1位,可以使用shift 2
:
true
false
----------------------------------------------------------------------------------
26. 随机数RANDOM
默认会产生0~32767的随机整数
例; 产生0~100内的随机数 echo $[$RANDOM%101]
--------------------------------------------------------------------
27. 函数
函数名()
{
函数体(一堆命令的集合,来实现某个功能)
}
----------
或者
function 函数名()
{
函数体(一堆命令的集合,来实现某个功能)
echo hello
echo world
}
----------------
28. 函数中return说明:
1. return可以==结束一个函数==。类似于循环控制语句break(结束当前循环,执行循环体后面的代码)。
2. return默认返回函数中最后一个命令状态值,也可以给定参数值,范围是0-256之间。
3. 如果没有return命令,函数将返回最后一个指令的退出状态值。
-----------
29. 函数调用
1. 写个函数,叫fun1.sh
#!/bin/bash
hello(){
echo "hello lilei $1"
}
2. 当前命令行调用
source命令用法:source FileName 作用:在当前bash环境下读取并执行FileName中的命令。 该命令通常用命令".”来替代
[root@MissHou shell04]# source fun1.sh (或者 . fun1.sh )
[root@MissHou shell04]#
[root@MissHou shell04]# hello 888
hello lilei 888
---------
30. 定义到用户的环境变量中(当用户打开bash的时候会读取该文件)
[root@MissHou shell05]# vim ~/.bashrc
文件中增加如下内容:
hello(){
echo "hello lilei $1"
}
-----------
31. 脚本中调用
#!/bin/bash
hello(){
echo "hello lilei $1"
}
hello // 直接这样写就调用了
-------------------------------------
32.
********************************************
*****************************************
注意:
1.
如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题,所以可以使用:`#!/bin/env 解释器`
#!/bin/env bash