Shell编程
shell简介
shell的作用
1.解释执行用户输入的程序或者指令
2.用户输入一条指令,shell解释一条
3.键盘输入指令,Linux给与响应 ----- 这个过程称之为交互式响应流程
shell是一块包裹着系统核心的壳,处于操作系统的最外层,与用户直接对话,shell可以把用户的输入,解释给操作系统, 然后处理操作系统的输出结果,输出到屏幕给用户看到结果。 ---- 翻译官
指令的工作流程
shell的分类和切换
shell解释器的版本
查看当前使用解释器版本
shell的修改
vim /etc/passwd
shell脚本
1. 当命令或者程序语句书写在文件中,我们去执行文件,读取其中的代码 ---- 这个文件就称之为 shell脚本
2. 在shell脚本中定义多条linux的指令,以及 选择分支,循环,函数,数组..... 然后将linux命令一次性执行完毕。
这种执行脚本文件的方式 ------ 非交互式
程序员在客户端敲指令,然后回车出结果 ------ 交互式
3. shell的脚本规则
在linux系统中 shell脚本(shell程序) 通常由 vim 编辑 bash shell 指令 , 逻辑控制语言 , 注释等组成
第一个shell程序
方式一
1.编辑文件
vim hello.sh
文件内容: echo "HelloWorld
2.解释文件
/bin/bash hello.sh # 自行指定文件的shell解释器版本 可以省略 (shebang)
或者
bash hello.sh
方式二
编辑文件
vim hello.sh
文件内容: echo "HelloWorld
1.给文件增加执行权限
chmod +x hello.sh
2.执行文件 # 文件要提供相对或者绝对路径
[root@localhost localhost]# /localhost/hello.sh
HelloWorld
方式三
编辑文件
vim hello.sh
文件内容: echo "HelloWorld
[root@localhost localhost]# source hello.sh
HelloWorld
等价于
[root@localhost localhost]# . hello.sh
HelloWorld
# source 文件.sh 等价于 . 文件.sh
方式四
1. 编辑文件
vim world.sh
#! /bin/bash
echo "Hello正统方式"
2. 执行文件
可以使用以上三种方式
Shebang (释伴)
文件内容 #! ------- shebang的两个符号
Shebang通常出现在类Unix系统的脚本中第一行,作为前两个字符。在Shebang之后,可以有一个或数个空白字符,后接解释器的绝对路径,用于指明执行这个脚本文件的解释器。在直接调用脚本时,系统的程序载入器会分析 Shebang 后的内容,将这些内容作为解释器指令,并调用该指令,将载有 Shebang 的文件路径作为该解释器的参数,执行脚本,从而使得脚本文件的调用方式与普通的可执行文件类似。例如,以指令#!/bin/sh开头的文件,在执行时会实际调用 /bin/sh 程序(通常是 Bourne shell 或兼容的 shell,例如 bash、dash 等)来执行。
注意
1. 如果没有指定 shebang 脚本执行的时候 默认使用的是 系统当前的shell解释器 $SHELL
2. 如果 #! 指定了解释器 但是没有执行该文件的权限 报错
3. 解释器的选择存在优先级
1. 运行脚本文件时 自行指定的 解释器 (无论写没写 shebang)
2. 若脚本文件中填充了 shebang 书写指令时,借助系统的shell解释器 但是shebang解析以后优先启用
3. 若脚本中未填充 shebang 且运行文件时未书写 解释器 使用 系统的解释器 $SHELL
脚本注释
1. 在shell脚本中 "#" 后面的内容就代表注释
2. 注释提供给开发者查看的,系统会忽略注释
3. 脚本注释的语法
# 注释内容
举例:
# 向界面输出HelloWorld
echo "HelloWorld"
脚本语言
shell脚本语言属于一种弱类型语言 : 无需声明变量类型 直接定义使用
例如: name="小黑" age=20 score=80.0
强类型:
int double char boolean
int a = 10 √
a = 15 √
a = "shuaihui" ×
弱类型:
var
var v = 10
v = 15 √
v = "zhangsan" √
shell会保留会话中用户曾提交的命令
# 查看历史命令记录 [包含文件中和内存中的历史记录]
history
# 查看文件中的历史指令记录 若误删了内存中的历史指令,可以借助 history -r 文件 进行恢复
[root@localhost localhost]# vim /root/.bash_histor
# 查看所有历史命令记录
history
列出历史命令以后 可以 选中 历史命令的编号 再次执行
# !历史命令的编号
# 查看前10条历史命令记录
history 10
history命令参数详解
-c 清空内存中历史命令
-r 可以从文件中恢复历史命令
shell变量
变量概念
变量是计算机内存存储数据的地方。是一种数据标记(房间号,标记了客人[数据]的位置) 数据存储在内存空间, 通过调用对应的变量名,即可获取对应的值。[变量名与值之间,包括等号 不能有空格]
# 定义一个变量
变量名=值 # shell规范中 所有的值都是字符串
例如:
name="小黑"
age="20"
score=1.2
#定义一个变量的案例
[root@localhost ~]# name="小黑"
[root@localhost ~]# echo "HelloWorld"
HelloWorld
[root@localhost ~]# echo HelloWorld
HelloWorld
[root@localhost ~]# echo $name
小黑
#获取变量的值
完整写法 ${变量名}
简化写法 $变量名
# 若变量名[在重合的作用域内]重复
name="小黑"
name="小白" # 指令执行,相当于修改变量name中保存的值
echo $name # 小白
变量名的规则
1. 名称定义要做到望文生义,要按照规则来 不能使用保留字,关键字 2. 只能包含数字,字母,下划线(_) 3. 不能以数字开头 4. 不能使用标点符号 5. 变量名要严格区分大小写
# 变量名严格区分大小写
[root@localhost ~]# name="小黑"
[root@localhost ~]# Name="小白"
[root@localhost ~]# echo $Name
小白
[root@localhost ~]# echo $name
小黑
# 以下命名不符合规则
change_123 OK!
change@123 error!
1change_123 error!
_change123 ok!
test_insert_student_info ok!
变量的分类
1. 本地变量
2. 全局变量
3. 局部变量
4. 特殊变量
5. 自定义的变量
# 安装软件 psmisc 查看父子 shell
yum -y install psmisc
# pstree
查看父子shell的关系
本地变量
在当前shell中有效(切换子shell , 子 shell 无法获取定义的变量)
注意:
1. 父 shell 进 子 shell 运行 携带 bash或者sh的指令即可
2. 子 shell 回 父 shell exit # 通过pstree 查看父子shell关系 以及当前所处的 shell
环境变量
环境变量也称之为全局变量.针对当前的shell以及任意的子shell 都有效。 环境变量也分为 自定义、内置。
每个用户都有自己的环境变量(全局变量)配置文件 ~/.bash_profile ~/.bashrc(个人) 优先加载并读取变量, 以个人的优先生效
2.全局配置文件 /etc/profile /etc/bashrc 但 系统建议最好创建在 /etc/profile.d/ 而非修改主文件 修改全局配 置文件 影响所有登录系统的用户 ---------- root有权修改
3.环境变量一般是指 使用 export内置命令导出的变量 , 用于定义shell的运行环境 保证shell命令的正确执行 shell设置登录的用户名 PATH路径 文件系统.....
4.环境变量可以在命令行中临时创建, 但是当用户退出终端时 命令丢失 在配置文件中定义,永久有效
检查系统环境变量(全局变量)
set # 输出所有变量 包含全局变量、局部变量
env # 只显示全局变量
declare # 输出所有变量 等同于 set
export # 显示和设置环境相关的变量值(等同于全局)
撤销系统环境变量
unset 变量名 # 删除变量或者函数
例如:
unset age;
设置只读变量
readonly # 在shell结束前,只允许获取变量的值 不允许修改
[root@localhost ~]# readonly age=20
[root@localhost ~]# echo $age
20
[root@localhost ~]# age=30
bash: age: 只读变量
设置临时的全局变量
export age1=30
环境变量初始化与加载顺序
局部变量
定义在函数内部的变量,只在函数内部有效
特殊变量
shell的特殊变量,用在比如 脚本 , 函数传递参数时使用
殊变量 $0 $1 $2的案例演示
结果为 ./special.sh --- 小黑 ---- abc
########################################
特殊变量$#的案例演示
获取参数的总个数
参数的总个数为: 5
#########################################
演示 $*的案例
结果为: 小黑 abc 小白 def 小兰
########################################
演示 $@ 的案例
结果为: 小黑 abc 小白 def 小兰
[root@localhost localhost]# cat special.sh
#! /bin/bash
echo '特殊变量 $0 $1 $2的案例演示'
echo '结果为' $0 '---' $1 '----' $2
echo '########################################'
echo '特殊变量$#的案例演示'
echo '获取参数的总个数'
echo '参数的总个数为:' $#
echo '#########################################'
echo '演示 $*的案例'
echo '结果为:' $*
echo '########################################'
echo '演示 $@ 的案例'
echo '结果为:' $@
# $* 和 $@ 的区别
[root@localhost localhost]# ./special2.sh 小黑 123 小白 456 小兰
演示 "$*" 的用法
小黑 123 小白 456 小兰
---------------------------------------
演示 "$@" 的用法
小黑
123
小白
456
小兰
[root@localhost localhost]# cat special2.sh
#! /bin/bash
echo '演示 "$*" 的用法'
for i in "$*"
do
echo "$i"
done
echo '---------------------------------------'
echo '演示 "$@" 的用法'
for a in "$@"
do
echo "$a"
done
$? 获取上一次指令执行的状态返回值 0 正确 非0失败可以自定义 exit 120 执行失败时echo? 就打印 120
$$ 当前 shell脚本的 进程号
$! 上一次后台进程的PID
$_ 获取上一次的命令执行时传递的最后一个参数
## 1. 演示$?
[root@localhost localhost]# ll /etc # 正确指令
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# ll /etcc # 路径错误
ls: 无法访问/etcc: 没有那个文件或目录
[root@localhost localhost]# echo $? # 上个命令执行失败,输出2
## 2. 演示 $$
[root@localhost localhost]# echo $$ # 执行失败时,输出的状态码
## 3. 演示 $_
[root@localhost localhost]# sh special.sh 小黑 小白
特殊变量 $0 $1 $2的案例演示
结果为 special.sh --- 小黑 ---- 小白
########################################
特殊变量$#的案例演示
获取参数的总个数
参数的总个数为: 2
#########################################
演示 $*的案例
结果为: 小黑 小白
########################################
演示 $@ 的案例
结果为: 小黑 小白
[root@localhost localhost]# echo $_ # 获取上一个命令的最后一个参数
小白
脚本控制返回值
[root@localhost localhost]# ./t1.sh 123 456 789
你必须传递两个参数
刚刚好传递了两个参数
[root@localhost localhost]# vim t1.sh
[root@localhost localhost]# ./t1.sh 123 456 789
你必须传递两个参数
[root@localhost localhost]# ./t1.sh 123 456
刚刚好传递了两个参数
[root@localhost localhost]# cat t1.sh
#! /bin/bash
[ $# -ne 2 ] && {
echo "你必须传递两个参数"
exit 119 # 终止程序运行,且返回119状态码以后 提供给当前shell的 $? 变量
}
echo "刚刚好传递了两个参数"
内置的shell命令
1. echo 打印输出内容
参数:
-n 不换行输出
-e 解析字符串中的特殊符号
##echo 案例演示
[root@localhost localhost]# echo 你瘦了;echo 你多吃点
你瘦了
你多吃点
[root@localhost localhost]# echo -n 你瘦了;echo 你多吃点
你瘦了你多吃点
[root@localhost localhost]# echo "你人还挺好"
你人还挺好
[root@localhost localhost]# echo "你人\n还挺好"
你人\n还挺好
[root@localhost localhost]# echo -e "你人\n还挺好"
你人
还挺好
2.eval 相当于把第二个指令当做参数传递给 eval
## eval案例演示
[root@localhost localhost]# ls < /etc
demo.sh hello.sh special2.sh special.sh t1.sh world.sh
[root@localhost localhost]# eval ls;cd /etc
demo.sh hello.sh special2.sh special.sh t1.sh world.sh
3.exec 不创建子进程 执行后续命令 且执行完毕后 自动 exit
## exec案例演示
[root@localhost localhost]# exec date
等价于
[root@localhost localhost]# date
[root@localhost localhost]# exit
字符串操作
字符串截取
# 从开头删除匹配最短 pcabcabc [p*c] -----> abcabc
## 从开头删除匹配最长 pab6666666c [p*c] -----> 空
% 从结尾删除匹配最短 pcabcapbc [p*c] -----> pcabca
%% 从结尾匹配删除最长 pcabcapbc [p*c] ----> 空
替换
${变量名/匹配模式/新值} 用新值替换第一个满足匹配模式的子字符串
${变量名//匹配模式/新值} 用新值代替所有满足匹配模式的子字符串
// 指定匹配内容截取
a*c 匹配开头是 a 中间任意个字符 结尾是 c 的字符串 ac abc a123456c
## 1
. 单# 与 双 ## 演示
## 2. ${#变量}
统计变量中保存字符串的长度
[root@localhost ~]# str1="changge123456changge"
[root@localhost ~]# echo $str1
changge123456changge
[root@localhost ~]# echo ${#str1}
20
## 3. ${变量名:start}
从 start下标开始(包含start) 截取字符串 ----------- 下标从0开始,依次递增
[root@localhost ~]# str1="changge123456changge"
[root@localhost ~]# echo $str1
[root@localhost ~]# echo ${str1:2}
angge123456changge
## 4. ${变量名:start:length}
提取start之后的length个字符,包含start
[root@localhost ~]# echo ${str1:2:5}
angge
## 5. ${变量名#关键词}
从头开始,删除匹配最短的第一个关键词
[root@localhost ~]# echo ${str1#ch}
angge123456changge
[root@localhost ~]# str3="234511654321"
[root@localhost ~]# echo ${str3#2*4} # 匹配最短的2-4
511654321
## 6. ${变量名##关键词}
[root@localhost ~]# str3="234511654321"
[root@localhost ~]# echo ${str3##2*4} # 匹配最长的2-4
321
## 7. ${变量名%关键字}
从结尾开始删除匹配最短
[root@localhost ~]# echo ${str2}
1234511654321
[root@localhost ~]# echo ${str2%1*4}
1234511654321
[root@localhost ~]# echo ${str2%4*1}
123451165
## 8. ${变量名%%关键字}
从结尾开始删除匹配最长
[root@localhost ~]# echo ${str2%%4*1}
123
## 9. ${变量名/匹配模式/str}
使用str替换第一个字符串中满足匹配模式的内容
[root@localhost ~]# str4="1234568812345688456"
[root@localhost ~]# echo ${str4}
1234568812345688456
[root@localhost ~]# echo ${str4/88/aa}
123456aa12345688456
[root@localhost ~]# echo ${str4//88/aa}
123456aa123456aa456
统计字符串长度
[root@localhost ~]# echo $str4
1234568812345688456
## 1. 办法1: ${#变量名} ---- 效率最高
[root@localhost ~]# echo ${#str4}
19
[root@localhost ~]# time echo ${#str4} # 获取指令的执行时长
19
real 0m0.000s
user 0m0.000s
sys 0m0.000s
## 2. 办法2:
[root@localhost ~]# echo $str4 | wc -L
19
[root@localhost ~]# time echo $str4 | wc -L
19
real 0m0.002s
user 0m0.000s
sys 0m0.001s
## 3. 办法3 利用 数值计算expr
[root@localhost ~]# time expr length "${str4}"
19
real 0m0.001s
user 0m0.001s
sys 0m0.000s
# 4. 办法4: awk统计长度 length函数
[root@localhost ~]# time echo $str4 | awk '{print length($0)}'
19
real 0m0.002s
user 0m0.000s
sys 0m0.001s
shell扩展变量
## 扩展变量1
result=${param:-word}
如果param变量中保存的值为空,返回word,赋值给result
[root@localhost ~]# param="123456789"
[root@localhost ~]# result=${param:-666666}
[root@localhost ~]# echo $result
123456789
[root@localhost ~]# result=${param2:-666666}
[root@localhost ~]# echo $result
666666
[root@localhost ~]# echo $param2
[root@localhost ~]#
## 扩展变量2
result=${param:=word}
如果param变量中保存的值为空 则 word 赋值给 param 同时 返回给 result
[root@localhost ~]# echo $param2
[root@localhost ~]# result=${param2:=888888}
[root@localhost ~]# echo $result
888888
[root@localhost ~]# echo $param2
888888
## 扩展变量3
${param:?word}
如果param变量中没有值,将word当做标准错误输出 否则 输出 param的变量值
#用于设置变量为空时导致的错误,返回错误信息
## 扩展变量4
${param:+word}
如果param变量中没有值,什么都不做 如果有值 将 word返回
父子shell
pstree 查看父子shell的关系
ps -ef
-f 展示 UID PID PPID
-e 列处所有进程信息
ps -ef --forest
shell的进程列表 : 需要使用 () 将这组指令包括进去 ------- 这种方式就称之为 进程列表
(cd ~;ls;pwd;echo "小黑";.........) --- 这些指令是交给多个 子 shell执行
检测是否在子shell环境中
linux默认的有关shell的变量
## BASH_SUBSHELL
该变量的值有特点: 如果是 0 就处于当前shell环境中执行 否则 就是开辟了子shell去执行
[root@localhost ~]# (cd ~;ls;pwd;echo "小黑黑");echo $BASH_SUBSHELL
anaconda-ks.cfg localhost cronDemo.sh
/root
小黑黑
0
## 一个父shell下开启多个平行的子shell去执行指令执行以后,自行回到父shel
子shell嵌套运行
[root@localhost ~]# (pwd;(pwd;(echo $BASH_SUBSHELL)))
/root
/root
3
数学运算
算数运算符
+ - 加法减法
* / % 乘法 取商 取模(取余) 5除以2 商是2 余数(模)是 1 5/2-----2 5%2-----1
** 幂运算 5的2次方: 5**2-------25 5的3次方: 5**3------125
++ -- 操作数自身增加或者减少1 a++ ++a
&& || ! 逻辑与 逻辑或 取反
< > <= >= == =(对于字符串也相当于比较) != 小于 大于 小于等于 大于等于 等于 不等于
= += -= *= /= %= 赋值运算符 num=1 num+=1 num*=3
算数运算命令
(()) 经常用于整数运算 效率很高
let 用于整数运算 等同于 (())
expr 可用于整数运算,还有其他额外功能
bc [需要先安装] Linux下的一个计算器程序(适合整数以及小数运算)
$[] 用于整数运算
运算操作符与运算命令
((i=i+1)) 运算后赋值。将 i+1 的运算结果赋值给变量 i 若要打印 echo $((i=i+1))
i=$((i+1)) 将表达式运算后的结果赋值给 i
((8>7&&5==5)) 可以进行比较操作 还可以加入逻辑与 逻辑或 经常用于条件判断
echo $((2+1)) 打印输出运算表达式的结果 需要在 (())前添加 $
## 1.有关逻辑运算 真(1) 假(0)
[root@localhost ~]# echo $((8>7))
1
[root@localhost ~]# echo $((6>7))
0
## 2. 逻辑运算符的演示 && || ! # !的案例?
[root@localhost ~]# echo $((6>7&&3>4))
0
[root@localhost ~]# echo $((6>7&&3<4))
0
[root@localhost ~]# echo $((7>6&&5>4))
1
[root@localhost ~]# echo $[!((8>7))]
0
## 3.算数运算
[root@localhost ~]# echo $((3+4))
7
[root@localhost ~]# echo $((3-4))
-1
[root@localhost ~]# echo $((3*4))
12
[root@localhost ~]# echo $((4/3))
1
[root@localhost ~]# echo $((4%3))
1
[root@localhost ~]# echo $((3/4))
0
[root@localhost ~]# echo $((3%4))
3
[root@localhost ~]# echo $((15000/22/8))
85
[root@localhost ~]# echo $((15000/22/8+2))
87
[root@localhost ~]# echo $((2+15000/22/8+2))
89
# 4. 幂运算
[root@localhost ~]# echo $((5**2))
25
[root@localhost ~]# echo $((5**3))
125
[root@localhost ~]# echo $((5**4))
625
## 5. 给变量赋值
[root@localhost ~]# num=100
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# ((num*3))
[root@localhost ~]# echo $num
100
[root@localhost ~]# ((num=num*3))
[root@localhost ~]# echo $num
300
[root@localhost ~]# sum=100
[root@localhost ~]# echo $((sum=sum*3))
300
[root@localhost ~]# add=10
[root@localhost ~]# echo $((add+=100))
110
[root@localhost ~]# echo $add
110
用于数值计算的命令
[root@localhost ~]# a=10
[root@localhost ~]# ((a=2+2**3-4%3+a))
[root@localhost ~]# echo $a
19
[root@localhost ~]# b=((2+2**3-4/4+4**2)) # 错误
-bash: 未预期的符号 `(' 附近有语法错误
[root@localhost ~]# b=$((2+2**3-4/4+4**2))
[root@localhost ~]# echo $b
25
[root@localhost ~]# ((b=2+2**3-4/4+4**2))
[root@localhost ~]# echo $b
25
注意:
(()) 只能对整数进行运算 -----> bc
[root@localhost ~]# ((c=1+100+2**3+1.2))
-bash: ((: c=1+100+2**3+1.2: 语法错误: 无效的算术运算符 (错误符号是 ".2")
特殊符号运算
++ 变量自增1
-- 变量自减1
a++ 先对变量a操作,然后再让a自增1
++a 先让a自增1,然后再复制给a
[root@localhost ~]# a=5
[root@localhost ~]# echo $((++a))
6
[root@localhost ~]# echo $a
6
[root@localhost ~]# b=5
[root@localhost ~]# echo $((b++))
5
[root@localhost ~]# echo $b
6
[root@localhost ~]# c=5
[root@localhost ~]# echo $((c--))
5
[root@localhost ~]# echo $c
4
[root@localhost ~]# d=5
[root@localhost ~]# echo $((--d))
4
[root@localhost ~]# echo $d
4
let的使用
## let 对变量的数值运算
[root@localhost ~]# num=5
[root@localhost ~]# let num=num+4
[root@localhost ~]# echo $num
9
[root@localhost ~]# let num+=1.2
-bash: let: num+=1.2: 语法错误: 无效的算术运算符 (错误符号是 ".2")
expr
## expr命令不太好用,基于空格传入参数 但是在shell中一些字符具备特殊含义
[root@localhost ~]# expr 5+3
5+3
[root@localhost ~]# echo $((5+3))
8
[root@localhost ~]# expr 5 + 3
8
[root@localhost ~]# expr 5 * 3
expr: 语法错误
[root@localhost ~]# expr 5 \* 3
15
[root@localhost ~]# expr 5 \+ 3
8
[root@localhost ~]# expr 5 % 3
2
[root@localhost ~]# expr 5 \% 3
2
## 注意 : 数值与运算符号之间需要加空格 运算符很容易识别失败 需要转义
[root@localhost ~]# expr 5 + 3 + 4 \* 2 -4
expr: 语法错误
[root@localhost ~]# expr 5 + 3 + 4 \* 2 - 4
12
[root@localhost ~]# expr 5 \> 6
0
[root@localhost ~]# expr 8 \> 6
1
expr的内置函数
length函数
## 案例
[root@localhost ~]# expr length 123456789
9
[root@localhost ~]# expr length 123456789
9
[root@localhost ~]# size="123456789"
[root@localhost ~]# expr length $size
9
[root@localhost ~]# size="123456789 "
[root@localhost ~]# expr length $size
9
expr的模式匹配
expr命令也支持模式匹配功能
两个特殊符号
: 冒号用于计算字符串的字符数量 gaosc 5个字符
.* 任意的字符串重复0次或多次
最后的模式 支持自定义
## 语法
expr 字符串 ":" ".*"
## 根据指定的字符获取 包括字符在内 字符及字符之前的 数量
[root@localhost ~]# expr test.jpg ":" ".*"
8
[root@localhost ~]# expr test.jpg ":" ".*j"
6
[root@localhost ~]# expr test.jpg ":" ".*p"
7
[root@localhost ~]# expr yc.png ":" ".*\.png"
6
[root@localhost ~]# expr yc.png ":" ".*\.jpg"
0
[root@localhost ~]# expr yc.jptg ":" ".*\.jpg"
0
[root@localhost ~]# expr yc.jpggggggggggggggggggg ":" ".*\.jpg"
6
bc命令
# 1. 安装 bc 软件
yum -y install bc
# 2.使用计算器
bc
bc命令结合管道符来计算
[root@localhost ~]# echo "4*4"
4*4
[root@localhost ~]# echo "4*4" | bc
16
[root@localhost ~]# echo "4.2*4" | bc
16.8
[root@localhost ~]# echo $num*1.2 | bc
6.0
[root@localhost ~]# result=`echo $num*1.2 | bc`
[root@localhost ~]# echo $result
6.0
bc应用的案例
## 计算1~1000的和
数学公式
1+2+3+4+5+6+...+999+1000
## 1.先想办法获取这些操作数
[root@localhost ~]# echo {1..1000}
## 2.将数字之间的空格替换为 +
[root@localhost ~]# echo {1..1000} | tr " " "+"
## 3.将上一步处理以后的字符串交给 bc 进行运算
[root@localhost ~]# echo {1..1000} | tr " " "+" | bc
500500
[root@localhost ~]# seq -s "+" 1000 | bc
500500
[root@localhost ~]# echo $((`seq -s "+" 1000`))
500500
###补充
seq 数字 # 打印1 2 3 4 5 ... 数字 数字之间分隔符默认为换行
seq -s 数字连接符 数字 # 指定连接符连接 1 2 3 4.... 数字
### 例如
seq -s "+" 10
输出 1+2+3+4+5+6+7+8+9+10
[root@localhost ~]# seq -s " + " 1000 | xargs expr
500500
read指令
可以在程序运行过程中,程序员输入数据
## 从标准输入中读取数据并赋值给指定变量
# 语法 read 变量名
[root@localhost ~]# read var
123 # 借助键盘标注输入设备,录入数据以后 保存在 var变量中
[root@localhost ~]# echo $var
123
## 从标准输入中输入多个值(用空格间隔),回车输入结束 第一个值给变量1 后续所有的值给变量2
## 语法 read 变量1 变量2
[root@localhost ~]# read first last
123 456 789 000 111 222
[root@localhost ~]# echo $first
123 # first保存第一个值
[root@localhost ~]# echo $last
456 789 000 111 222 # 其余的值存入 last变量中
[root@localhost ~]# read a b c # a b两个变量中各存一个值 其余赋值给 c
123 456 789 123
[root@localhost ~]# echo $a
123
[root@localhost ~]# echo $b
456
[root@localhost ~]# echo $c
789 123
## 若read后未指定变量名,则数据赋值给变量 REPLY
[root@localhost ~]# read
123
[root@localhost ~]# echo $REPLY
123
## 把多个值存入一个变量中
语法:
read -a 变量
[root@localhost ~]# read -a array
123 456 789 456 789 123 000
[root@localhost ~]# echo ${array[0]}
123
[root@localhost ~]# echo ${array[1]}
456
[root@localhost ~]# echo ${array[6]}
000
[root@localhost ~]# echo ${array[@]}
123 456 789 456 789 123 000
## 限定输入读取的时长
语法:
read -t 时间 变量
## 测试数据
read.sh
#!/bin/bash
echo "请在五秒内完成密码录入并回车,请输入密码:"
read -t 5 passwd ## 在5秒内完成信息录入并回车 否则数据不会保存
echo "--------------------------"
echo "您输入的密码为:"$passwd
## 操作界面
[root@localhost localhost]# ./read.sh
请在五秒内完成密码录入并回车,请输入密码:
123456
--------------------------
您输入的密码为:123456
## 允许输入反斜杠
语法:
read -r 变量名
[root@localhost localhost]# read var
123 \
>
[root@localhost localhost]# read -r var
123 \ 123 \ 123
## 默认是 回车键代表结束输入
read -d "符号" 变量名
[root@localhost localhost]# read -d ":" var
123 :[root@localhost localhost]# read -d ":" var
123
## 此时回车结束符被 冒号 覆盖
:[root@localhost localhost]#
## 从标准输入中读取两个字符 并存入变量 不需要按回车读取结束
语法:
read -n 2 变量名
[root@localhost localhost]# read -n 2 var
12[root@localhost localhost]#
shell测试
shell测试语法参数
得出一个指令真假的概念(文件是否存在,文件夹是否存在.......)
条件测试语法 | 说明 |
---|---|
test 测试表达式 | test 与 测试表达式之间至少一个空格 |
[ 测试表达式 ] | 用法与test一致 但是测试表达式左右两侧都必须有空格 |
[[ 测试表达式 ]] | 用法要求与 [] 一致 双中括号是对单中括号的补充 |
(( 测试表达式 )) | 测试表达式两端不需要空格 |
test条件测试
test命令评估表达式,它的结果是真,还是假 如果条件为真 那么 命令执行状态码的结果就是 0 若条件为假 执行 状态码不为0 执行状态码获取 $?
if(条件为真){
exit 0 ; 执行状态码为0
}else{
exit 1; 条件为假 执行状态码不为0
}
文件类型参数
参数介绍:
-e : 判断指定文件(文件夹)是否存在 存在即为真 不存在 为假
[root@localhost localhost]# test -e /a.txt
### 当结果为真,也就是文件存在 命令执行状态码是 0
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# test -e /d.txt
### 当结果为假,也就是文件不存在 命令执行状态码是 1
[root@localhost localhost]# echo $?
1
[root@localhost localhost]# str="/a.txt"
[root@localhost localhost]# test -e $str
[root@localhost localhost]# echo $?
0
语法参数 ------ 判断文件类型
-e 指定文件名是否存在
-f 指定文件名是否为文件
-d 指定文件名是否为目录
-b 指定的文件名是否为 block device装置
-c 指定的文件名是否为 character device装置
-S 指定的文件名是否为 Socket文件
-p 指定文件名是否为一个FIFO文件
-L 指定文件名是否为一个链接档
文件权限参数
-r 判断指定文件是都具备 读权限
-w 判断指定文件是否具备 写权限
-x 判断指定文件是否具备 执行权限
-u 判断指定文件是否具备 SUID的属性
-g 判断指定文件是否具备 SGID的属性
-k 判断指定文件是否具备 Sticky bit的属性
-s 判断指定文件是否为 非空白文件
|- 真 是非空白文件 -----> 有内容
|- 假 不是非空白文件 -----> 没有内容
[root@localhost localhost]# ll hello.sh
-rw-r--r--. 1 root root 18 11月 13 10:43 hello.sh
[root@localhost localhost]# test -r hello.sh
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# test -w hello.sh
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# test -x hello.sh
[root@localhost localhost]# echo $?
1
[root@localhost localhost]# test -s a.txt
[root@localhost localhost]# echo $?
1
[root@localhost localhost]# cat -E a.txt # 没有内容输出
[root@localhost localhost]#
文件比较参数
## 两个文件之间的比较
-nt (newer than) file1 -nt file2 判断 file1 是否比 file2 新
-ot (older than) file1 -ot file2 判断 file1 是否比 file2 旧
-ef file1 -ef file2 判断 file1 与 file2 是否为同一文件 可用于判断硬链接[判断这两个文件是否指向
同一个inode ]
### -nt 参数的演示
50674120 -rw-r--r--. 2 root root 11 11月 15 10:34 file1_hard.txt
50674120 -rw-r--r--. 2 root root 11 11月 15 10:34 file1.txt
50674122 -rw-r--r--. 1 root root 0 11月 15 10:35 file2.txt
[root@localhost localhost]# test file2.txt -nt file1.txt
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# test file1.txt -nt file2.txt
[root@localhost localhost]# echo $?
1
## -ot 参数的演示
[root@localhost localhost]# test file1.txt -ot file2.txt
[root@localhost localhost]# echo $?
0
## -ef 参数的演示
[root@localhost localhost]# test file1.txt -ef file2.txt
[root@localhost localhost]# echo $?
1
[root@localhost localhost]# test file1.txt -ef file1_hard.txt
[root@localhost localhost]# echo $?
0
整数之间的判定参数
## 关于两个整数之间的判定(针对变量数值大小的比较判断)
推荐是 [] 和 test使用比较的字符写法 因为使用 符号 > < != = >= <= 需要转义
-eq 两数值相等
-ne 两数值不等
-gt num1 -gt num2 num1是否大于num2
-lt num1 -lt num2 num1 是否小于 num2
-ge num1 -ge num2 num2 是否大于等于 num2
-le num1 -le num2 num1 是否小于等于 num2
[root@localhost localhost]# a=10
[root@localhost localhost]# b=20
[root@localhost localhost]# test $a -eq $b
[root@localhost localhost]# echo $?
1
[root@localhost localhost]# test $a -ne $b
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# test $a -gt $b
[root@localhost localhost]# echo $?
1
[root@localhost localhost]# test $a -lt $b
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# test $a -le $b
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# test $a -ge $b
[root@localhost localhost]# echo $?
1
判定字符串的参数
-z
test -z 字符串 判断字符串是否为空 "" 若为空 则为真
若非空 则为假
-n
test -n 字符串 判断字符串是否为 非空 ## -n 可以省略
|- 若字符串是 非空 ------ 有内容 真
|- 若字符串不是非空 ------ 没有内容 假
特例:
test $str1 = $str2 判断 str1 是否 等于 str2 若相等 回传 true
test $str1 != $str2 判断 str1 是否和 str2 不等 不等为 true 相等为假
多重条件判断
-a (and)两种情况同时成立 例如 test -r file1 -a -x file1 判断 file1是否具备读写权限,都具备返回真,
否则返回假
-o (or)两种情况任何一个成立 例如 test -r file1 -o -w file1 判断 file1 是否具备读权限或者写权限
若具备读或者写权限,则返回真
! 取反 例如 test ! -r file1 若file1具备读权限,则为假 反之为真
[root@localhost localhost]# test -r file1.txt -a -w file1.txt
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# ll file1.txt
-rw-r--r--. 2 root root 11 11月 15 10:34 file1.txt
shell对于真假的判断逻辑。 提供了 && || !
A条件 && B条件
当A成立,才会执行B条件
A条件 || B条件
当A条件不成立时,才会执行B
## A条件 && B代码 A成立,才会执行B
[root@localhost localhost]# test -e heiheihei.txt && echo "这个嘿嘿嘿文件存在"
[root@localhost localhost]# touch heiheihei.txt
[root@localhost localhost]# test -e heiheihei.txt && echo "这个嘿嘿嘿文件存在"
这个嘿嘿嘿文件存在
## touch指令有两个作用: 1. 新建文件 2.修改文件的创建时间
[root@localhost localhost]# test -e heihei.txt && echo "这个嘿嘿嘿文件存在" || touch heihei.txt
[root@localhost localhost]# test -e heihei.txt && echo "这个嘿嘿嘿文件存在" || touch heihei.txt
这个嘿嘿嘿文件存在
[root@localhost localhost]# test -e hello && echo "hello文件夹已存在" || mkdir hello
[root@localhost localhost]# test -e hello && echo "hello文件夹已存在" || mkdir hello
hello文件夹已存在
### 判断 happy.txt 是否存在,若存在,判断是否为文件 思路[伪代码]
if( 文件存在 ){
if (是文件){
是文件
}else{
不是文件
}
}else{
不存在
}
中括号的条件测试
脚本中经常中括号进行条件测试
中括号[] test 和 [] 作用一样
### 注意事项
1. 在中括号中使用变量的值 "$变量名"
2. 中括号与测试表达式前后都要有空格
3. 若要进行比较,在中括号和 test 语句中使用 字符写法 ( -eq -ne -gt -lt -ge -le )
### test 的文件存在判定写法
[root@localhost localhost]# test -e test.txt && echo "文件存在" || echo "文件不存在"
文件不存在
[root@localhost localhost]# [ -e test.txt ]
[root@localhost localhost]# echo $?
1
##### [] 的文件判定存在写法 作用与 test 一致
[root@localhost localhost]# [ -e test.txt ] && echo "文件存在" || echo "文件不存在"
文件不存在
[root@localhost localhost]# filePath="/localhost/t1.sh"
### [] 判定是否为文件
[root@localhost localhost]# [ -f $filePath ] && echo " $filePath 是文件" || echo "不是文件"
/localhost/t1.sh 是文件
###[] 判定是否为文件夹
[root@localhost localhost]# [ -d "/localhost" ] && echo "是文件夹" || echo "不是文件夹"
是文件夹
###[] 判定文件是否有读权限,若有,则查看文件内容
[root@localhost localhost]# [ -r "$filePath" ] && cat $filePath
[root@localhost localhost]# [ -w "$filePath" ] && echo "HelloWorld" && cat $filePath
HelloWorld
#! /bin/bash
[ $# -ne 2 ] && {
echo "你必须传递两个参数"
exit 119 # 终止程序运行,且返回119状态码以后 提供给当前shell的 $?变量
}
echo "刚刚好传递了两个参数"
[root@localhost localhost]# [ -w "$filePath" ] && echo "HelloWorld" >> $filePath && cat $filePath
[root@localhost conf]# [ file1.txt -nt file2.txt ] && echo "file1.txt日期更新" || echo "file2.txt日期更新"
file2.txt日期更新
[root@localhost conf]# cd /localhost
[root@localhost localhost]# [ file1.txt -nt file2.txt ] && echo "file1.txt日期更新" || echo "file2.txt 日期更新"
file2.txt日期更新
[root@localhost localhost]# a=10
[root@localhost localhost]# b=20
[root@localhost localhost]# c=10
[root@localhost localhost]# d=5
[root@localhost localhost]# [ "$a" -eq "$b" ] && echo "两个数相等" || echo "两个数不相等"
两个数不相等
[root@localhost localhost]# [ 10 -eq 20 ] && echo "两个数相等" || echo "两个数不相等"
两个数不相等
[root@localhost localhost]# [ 10 -eq 20 ] && echo "两个数相等" || echo "两个数不相等"
两个数不相等
[root@localhost localhost]# ss=""
[root@localhost localhost]# [ -n "$ss" ] && echo $ss || echo "字符串为空"
字符串为空
[root@localhost localhost]# [ -n " " ] && echo $ss || echo "字符串为空"
[root@localhost localhost]# expr length "abc"
3
[root@localhost localhost]# expr length ""
0
[root@localhost localhost]# expr length " "
3
[root@localhost localhost]# [ 2 > 1 ] && echo "前者更大" || echo "后者更大"
前者更大
[root@localhost localhost]# [ 2 > 3 ] && echo "前者更大" || echo "后者更大"
前者更大
[root@localhost localhost]# [ 2 \> 3 ] && echo "前者更大" || echo "后者更大"
后者更大
双中括号
对单中括号的补充: 双中括号中 还支持 正则处理 在双中括号中 不需要转义字符可以识别特殊符号] 与 (()) 内部使用 比较字符 或者 比较符号 都可
### [[ 表达式 ]] 双中括号内部识别特殊字符
[root@localhost localhost]# [[ "$a" > "$b" ]] && echo "前者比后者大" || echo "后者比前者大"
后者比前者大
[root@localhost localhost]# [[ "$a" -gt "$b" ]] && echo "前者比后者大" || echo "后者比前者大"
后者比前者大
逻辑判断符号
&& -a
与运算 两边都为真 结果才为真
|| -o
或运算 两边有一个为真,结果就为真
[root@localhost localhost]# file1="/localhost/a.txt"
[root@localhost localhost]# file2="/localhost.txt"
[root@localhost localhost]#
[root@localhost localhost]#
[root@localhost localhost]# [ -e "$file1" -a -f "$file1" ] && echo "yes" || echo "no"
yes
[root@localhost localhost]# [ -e "$file2" -a -f "$file2" ] && echo "yes" || echo "no"
no
[root@localhost localhost]# [ -e "$file2" -o -f "$file2" ] && echo "yes" || echo "no"
no
[root@localhost localhost]# [ -e "$file2" -o -f "$file1" ] && echo "yes" || echo "no"
yes
## !表示对 -e "$file2" 结果取反 得到真 第二条件还是 假 真 -a 假 ----->假
[root@localhost localhost]# [ ! -e "$file2" -a -f "$file2" ] && echo "yes" || echo "no"
no
## 真 -a 假 --------> 假
[root@localhost localhost]# [ -e "$file1" -a -f "$file2" ] && echo "yes" || echo "no"
no
## 真 -a !(假)-------------真 -a 真 ------> yes
[root@localhost localhost]# [ -e "$file1" -a ! -f "$file2" ] && echo "yes" || echo "no"
yes
## 真 && 假 ------> no
[root@localhost localhost]# [[ -e "$file1" && -f "$file2" ]] && echo "yes" || echo "no"
no
## !(真) && 假 ------ 假 && 假 -----> no
[root@localhost localhost]# [[ ! -e "$file1" && -f "$file2" ]] && echo "yes" || echo "no"
no
## !(子shell执行返回假) -----> 真 yes
[root@localhost localhost]# [[ ! (-e "$file1" && -f "$file2") ]] && echo "yes" || echo "no"
yes
if语句
单分支if
if 语句
单分支 if
if [ 条件表达式 ]
then
代码
fi
简化写法
if [ 条件表达式 ];then
代码
fi
[root@localhost localhost]# cat if.sh
#! /bin/bash
echo "请输入(1-3)之间任意一个数字:"
read var1
if [ "$var1" -eq 1 ]
then
echo "黄焖鸡米饭出餐成功"
fi
if [ "$var1" -eq 2 ];then
echo "麻辣香锅出餐成功"
fi
if [ "$var1" -eq 3 ]
then
echo "盖浇饭出餐成功"
fi
if语句的嵌套
if的嵌套 不要超过 三层
if [ 条件表达式 ]
then
代码
if [ 条件表达式 ]
then
代码
fi
fi
[root@localhost localhost]# cat if2.sh
#! /bin/bash
echo "请输入金额:"
read money
if [ "$money" -gt 1000000 ]
then
echo "先买辆车"
money=$((money-300000))
if [ "$money" -gt 1000000 ]
then
echo "再买个房"
fi
fi
if-else结构
if [ 条件表达式 ]
then
代码1
else
代码2
fi
### if-else 结构中可以继续嵌套
### 执行流程: 首先执行条件表达式的判断,若条件表达式成立,则执行代码1 若条件表达式不成立 则执行代码2
[root@localhost localhost]# cat happy.sh
#! /bin/bash
file1="/localhost/happy.txt"
if [ -e "$file1" ]
then
if [ -f "$file1" ]
then
echo "$file1 是文件"
else
echo "存在,但不是文件"
fi
else
echo "不存在,你可以新建"
fi
[root@localhost localhost]# cat happy.sh
#! /bin/bash
# file1="/localhost/happy.txt"
if [ -e "$1" ]
then
if [ -f "$1" ]
then
echo "$1 是文件"
else
echo "存在,但不是文件"
fi
else
echo "不存在,你可以新建"
fi
多分支
if [ 条件表达式1 ]
then
代码1
elif [条件表达式]
then
代码2
elif [条件表达式]
then
代码3
....
else
代码
fi
#### 多分支 不要超过三层
### 买车
资金 10W 以内
买 秦
10W ~ 20W
买宋
20W ~ 30W
买su7
30W 以上
买房
[root@localhost localhost]# cat car.sh
#! /bin/bash
echo "请输入资金:"
read money
if [ "$money" -lt 100000 ]
then
echo "买帝豪"
elif [ "$money" -lt 200000 ]
then
echo "买比亚迪"
elif [ "$money" -lt 300000 ]
then
echo "买亚洲龙"
else
echo "买房"
fi
函数
函数是一段功能代码,用来解决shell编程中冗余代码[重复且不连续出现的功能性代码]的问题
### 1. 先定义函数
函数名(函数的唯一标识) + 函数体(功能代码)
### 2. 调用函数
### 函数定义的语法
## 1. 标准shell的函数定义
function 函数名(){
函数体
linux命令
if-else
循环
变量----(局部变量)
return 返回值
}
## 2. 简化写法1
function 函数名{
函数体
linux指令
if-else
循环
变量定义使用
return 返回值
}
## 3. 简化写法2
函数名(){
函数体
return 返回值;
}
# 定义函数
function print(){
echo "床前明月光"
echo "疑是地上霜"
echo "举头望明月"
echo "低头思故乡"
return 10
}
# 函数调用
print
print
执行函数时,直接写函数名即可 无需添加其他内容
函数必须先定义,再执行 ----- shell脚本是自上向下加载执行
想要在函数内部定义局部变量,使用 local 关键字
函数如果单独写入一个文件里,建议使用 source 去执行该文件
函数返回的结果,可以通过 $? 进行获取
return语句和exit语句
相同点:
都可以让程序返回
不同点:
1. return 只是代表当前函数执行结束,返回一个结果(返回值)
2. exit 代表当前文件执行结束
3. exit 结束当前shell环境,回到上一层 父shelll
函数实践
[root@localhost localhost]# cat fun3.sh
#! /bin/bash
#定义函数
function heihei(){
cd ~
echo "我准备创建一个文件,并追加写入信息"
echo "小黑6666" >> ./demo.txt
return 100
}
#调用函数(执行函数)
heihei
[root@localhost localhost]# ./fun3.sh ##### 开启子shell执行函数,变量和函数被加载到子shell环境中
我准备创建一个文件,并追加写入信息
[root@localhost localhost]# echo $?
100
[root@localhost localhost]# cat ~/demo.txt
小黑6666
小黑6666
小黑6666
小黑6666
小黑6666
[root@localhost localhost]# set | grep "heihei"
[root@localhost localhost]# ^C
[root@localhost localhost]# heihei ### 此时 函数和变量位于子shell环境 父shell 拿不到
-bash: heihei: 未找到命令
[root@localhost localhost]# source fun3.sh ### 将执行的变量和函数 引入当前的 shell环境[source其实是引用
当前的shel环境去执行文件 不开启子shell]
我准备创建一个文件,并追加写入信息
[root@localhost ~]# set | grep "heihei"
heihei ()
[root@localhost ~]# heihei
我准备创建一个文件,并追加写入信息
[root@localhost ~]# cat fun4.sh
#! /bin/bash
# 定义函数
ma(){
echo "ma函数被调用执行---------"
return 100
}
mb(){
echo "mb函数被调用执行"
return 110
}
#调用函数
ma
mb ### 后被调用 返回值 110 覆盖了 100
[root@localhost ~]# chmod +x fun4.sh
[root@localhost ~]# ./fun4.sh
ma函数被调用执行---------
mb函数被调用执行
[root@localhost ~]# echo $?
110
对于脚本的加载 在创建一个 fun5.sh 该脚本就是读取 ma 函数并调用
[root@localhost ~]# cat fun5.sh
#! /bin/bash
# 加载文件内的函数
[ -e ~/fun4.sh ] && . ~/fun4.sh || exit
#执行函数
ma
mb
函数脚本传入参数
分支结构--case
case 语句,主要是针对一个变量,进行多次 值比较 case语句相对 if来说 较为简便
语法:
case "变量" in
值1)
代码1
;;
值2)
代码2
;;
值3)
代码3
;;
*)
代码4
esac
类似于
if---elif--elif----elif---else
[root@localhost localhost]# cat case1.sh
#! /bin/bash
echo "请输入点餐编号(1~3):"
read num
case "$num" in
"1")
echo "黄焖鸡米饭出餐"
;;
"2")
echo "鸭腿饭出餐"
;;
"3")
echo "麻辣香锅出餐"
;;
*)
echo "您输入的数据不存在"
esac
[root@localhost localhost]# chmod +x case1.sh
[root@localhost localhost]# ./case1.sh
请输入点餐编号(1~3):
1
黄焖鸡米饭出餐
[root@localhost localhost]# ./case1.sh
请输入点餐编号(1~3):
2
鸭腿饭出餐
[root@localhost localhost]# ./case1.sh
请输入点餐编号(1~3):
3
麻辣香锅出餐
[root@localhost localhost]# ./case1.sh
请输入点餐编号(1~3):
4
您输入的数据不存在
循环结构
连续出现的功能性代码
shell循环有四种
while 设置条件,条件成立,循环就开始 之道循环条件不满足或者跳出结构位置
until 和whilc循环恰恰相反 条件不成立 循环开始 直到条件成立 循环结束
for
select
while 和 for 较为常用
while
主要用于程序的后台运行,需要持续运行的守护进程
while [ 条件表达式 ]
do
代码
done
### 无限次打印 HelloWorld
#! /bin/bash
num=1
while [ "$num" -lt 2 ]
do
echo "HelloWorld"
done
echo "while结构结束"
### 打印10次HelloWorld
1. 计数器
2. 打印一次 计数器++
3. 计数器的值 <= 10
[root@localhost localhost]# cat while1.sh
#! /bin/bash
num=1
while [ "$num" -lt 11 ]
do
echo "HelloWorld"
((num+=1))
done
echo "while结构结束"
### 每3秒输出一次系统负载
#! /bin/bash
while [ 1 -lt 2 ]
do
uptime >> /localhost/uptime2.log # 打印系统的负载
sleep 3 # 进程休眠3秒
done
###
指令 & ## 将进程放到后台运行
例如:
bash load1.sh &
jobs -l ## 查看后台正在运行的进程
[1]+ 2165 运行中 bash load1.sh &
## 计算 1+2+3+4+...+999+1000
#! /bin/bash
# 类和变量
sum=0
num=1
while [ $num -le 1000 ]
do
((sum=sum+num))
((num++))
done
# echo 是打印技术内容以后自动换行
# echo "1~1000的和为: $sum"
printf "1~1000的和为:$sum \n"
printf "HelloWorld"
printf 在脚本中应用的比 echo 更广泛 ----- 可移植性强
语法:
printf 格式 展示的数据
printf使用文本或者空格分隔参数,也可以使用格式化字符串 还可以指定字符串的宽度,左右对其的方式
默认不换行 想换行 可以手动添加特殊字符 \n --- 换行符
[root@localhost localhost]# cat printf1.sh
#! /bin/bash
printf "%-10s %-8s %-4s %-8s %-4s \n" 姓名 性别 体重 年龄 成绩
printf "%-10s %-8s %-4s %-8s %-4.1f \n" 小黑 男 180 30 68.3214
printf "%-10s %-8s %-4s %-8s %-4.1f \n" 小白 女 100 25 85.6789
printf "%-10s %-8s %-4s %-8s %-4.1f \n" 小兰 女 80 30 85.6666
[root@localhost localhost]# bash printf1.sh
姓名 性别 体重 年龄 成绩
小黑 男 180 30 68.3
小白 女 100 25 85.7
小兰 女 80 30 85.7
%s 格式替换符 输出一个字符串
%c 格式替换符 输出一个字符
%d 格式替换符 整型输出
%f 格式替换符 输出小数
%-10s 指一个宽度为10的字符 (- 表示左对齐 没有则表示右对齐) 任何字符都会被显示在10个字符的宽度内 如
果内容不够10个字符,使用空格填充 若内容超过10个字符 超过也会将内容显示出来
until
不满足条件,才执行 满足则跳出结构
[root@localhost localhost]# cat until1.sh
#! /bin/bash
num=1
until [ $num -gt 10 ]
do
# 不满足条件才执行
echo "HelloWorld"
((num++))
done
for循环
写法 1:
for 变量 in 变量取值的列表
do
代码
done
执行流程:
变量代表分别获取每个值 值取完了 结构退出
写法2:
for ((expr1;expr2;expr3))
for ((变量初始化定义;设置变量的取值范围;变量递增递减))
C语言
for(int i=0;i<=10;i++)
[root@localhost localhost]# cat for1.sh
#! /bin/bash
for var in 1 2 3 4 5 6 7 8 9 10
do
echo $var
done
echo "------------------------------------"
for var in {1..10}
do
echo $var
done
echo "-------------------------------------"
for var in `seq 10`
do
echo $var
done
##打印10次helloWorld
[root@localhost localhost]# cat for2.sh
#! /bin/bash
for var in {1..10}
do
echo "HelloWorld"
done
## 计算 1+2+3+4+...+999+1000
[root@localhost localhost]# cat for3.sh
#! /bin/bash
sum=0
for var in {1..1000}
do
((sum=var+sum))
done
echo "1~1000的和为 $sum"
## 打印 1 ~ 10 第二种写法
[root@localhost localhost]# cat for4.sh
#! /bin/bash
for ((num=1;num<=10;num++))
do
echo $num
done
## 列出某个目录下的文件
[root@localhost localhost]# ls /localhost
1 b.txt demo.sh for1.sh fun1.sh happy.txt hello.sh printf1.sh t1.sh
while1.sh
3 car.sh file1_hard.txt for2.sh fun2.sh heiheihei.txt if2.sh read.sh
test_and_or.sh while2.sh
abc.sh case1.sh file1.txt for3.sh fun3.sh heihei.txt if.sh special2.sh
until1.sh world.sh
a.txt c.txt file2.txt for4.sh happy.sh hello load1.sh special.sh
uptime2.log
[root@localhost localhost]# vim for5.sh
[root@localhost localhost]# cat for5.sh
#! /bin/bash
for file in `ls /localhost`
do
echo $file
done
## 列出某个文件夹下所有的文件(包含子文件夹内部的文件)
思路:
for var in 目录
do
1.var 可能是文件
echo $var
2. var 是个文件夹
列出该文件夹下的所有文件
----- 开发函数(列出指定文件夹下所有的文件)
[root@localhost localhost]# cat fun8.sh
#! /bin/bash
# 函数的能:列出指定文件夹下所有的文件
function list_files(){
for var in `ls $1` # $1是目录
do
dir_file="$1/$var" # 例如 $var hello文件夹 /localhost/hello
# 进行目录的递归搜索
# 搜索获取的 var 可能是文件 也可能是目录
# -f判断是否为文件 -d 判断是否为目录
# 若 var 是文件 打印
# 若 var 是目录 再次调用该函数
if [ -f "$var" ]
then
echo "$dir_file"
else
list_files "$dir_file"
fi
done
}
list_files $1
循环控制
中断循环
办法1:
循环条件不满足
办法2:
break 中断循环
continue 直接中断本次循环,进入下一次
exit 退出脚本,退出当前shell
return 用在函数中 结束函数的作用
break 关键字 break n [n代表跳出的循环层数]
##打印6次HelloWorld
[root@localhost localhost]# cat break1.sh
#! /bin/bash
for var in {1..10}
do
if [ $var -le 6 ]
then
echo "HelloWorld"
else
break
fi
done
## break n 的特点
[root@localhost localhost]# cat break2.sh
#! /bin/bash
for var in {1..10} # 外层循环
do
echo "外层循环的执行"
for tmp in {1..10}
do
if [ $tmp -le 6 ]
then
printf "$tmp "
else
break
fi
done
printf "\n"
done
[root@localhost localhost]# bash break2.sh
外层循环的执行
1 2 3 4 5 6
外层循环的执行
1 2 3 4 5 6
外层循环的执行
1 2 3 4 5 6
外层循环的执行
1 2 3 4 5 6
外层循环的执行
1 2 3 4 5 6
外层循环的执行
1 2 3 4 5 6
外层循环的执行
1 2 3 4 5 6
外层循环的执行
1 2 3 4 5 6
外层循环的执行
1 2 3 4 5 6
外层循环的执行
1 2 3 4 5 6
[root@localhost localhost]# bash break2.sh
外层循环的执行
1 2 3 4 5 6 [root@localhost localhost]# cat break2.sh
#! /bin/bash
for var in {1..10} # 外层循环
do
echo "外层循环的执行"
for tmp in {1..10}
do
if [ $tmp -le 6 ]
then
printf "$tmp "
else
break 2 ## 跳出第二层循环
fi
done
printf "\n"
done
contine 跳过本次循环,直接进入下一次循环
[root@localhost localhost]# bash break1.sh
HelloWorld 1
HelloWorld 2
HelloWorld 3
HelloWorld 4
HelloWorld 5
HelloWorld 6
HelloWorld 8
HelloWorld 9
HelloWorld 10
[root@localhost localhost]# cat break1.sh
#! /bin/bash
for var in {1..10}
do
if [ $var -eq 7 ]
then
continue
fi
echo "HelloWorld $var"
done
数组
数组变量中,可以存储多个值。
数组,就是多个元素的集合,能够把多个元素,通过一个变量名进行存储 然后再给元素挨个打标记[下标]
特征:
1. 数组内的值相互独立
2. 数组内每个值的标识-----下标{可以连续 可以不连续}
数组定义的语法
数组名=(值1 值2 值3 值4...)
[root@localhost localhost]# name="小黑 小白 小兰 小红"
[root@localhost localhost]# echo $name
小黑 小白 小兰 小红
[root@localhost localhost]# set | grep "name"
name='小黑 小白 小兰 小红'
[root@localhost localhost]# array1=(小黑 小白 小兰 小红)
[root@localhost localhost]# set | grep "array1"
array1=([0]="小黑" [1]="小白" [2]="小兰" [3]="小红")
基础操作
## 1. 声明并赋值
array=("小黑" "小白" "小兰")
## 2. 键值对的赋值方式来创建数组
heros=([0]="程咬金" [1]="花木兰" [2]="芈月" [3]="伽罗")
heros2=([3]="小乔" [1]="大乔" [5]="安其拉" [2]="典韦")
## 3.动态定义数组
myArray=(`ls /localhost`) ## 反引号的特点是先执行指令,再将指令输出
myArray1=($(ls /localhost)) ## 作用同上
## 4. 采用命令创建数组
declare -a 数组名 ## 不推荐
获取元素
## 1. 获取指定数组元素
${数组名[下标]}
[root@localhost localhost]# echo ${heros[0]}
程咬金
[root@localhost localhost]# echo ${heros[1]}
花木兰
## 2.获取所有数组元素
[root@localhost localhost]# echo ${heros[*]}
程咬金 花木兰 芈月 伽罗
[root@localhost localhost]# echo ${heros[@]}
程咬金 花木兰 芈月 伽罗
## 3.获取数组长度
[root@localhost ~]# echo ${#heros[@]}
4
[root@localhost ~]# echo ${#heros[*]}
4
修改元素
[root@localhost localhost]# heros=([0]="程咬金" [1]="花木兰" [2]="芈月" [3]="伽罗")
[root@localhost localhost]# set | grep "heros"
heros=([0]="程咬金" [1]="花木兰" [2]="芈月" [3]="伽罗")
[root@localhost localhost]# heros2=([3]="小乔" [1]="大乔" [5]="安其拉" [2]="典韦")
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# set | grep "^sero"
[root@localhost localhost]# set | grep "^hero"
heros=([0]="程咬金" [1]="花木兰" [2]="芈月" [3]="伽罗")
heros2=([1]="大乔" [2]="典韦" [3]="小乔" [5]="安其拉")
[root@localhost localhost]# heros2=([3]="小乔" [1]="大乔" [5]="安其拉" [2]="典韦" [1]="妲己")
[root@localhost localhost]# echo $?
0
[root@localhost localhost]# set | grep "^hero"
heros=([0]="程咬金" [1]="花木兰" [2]="芈月" [3]="伽罗")
heros2=([1]="妲己" [2]="典韦" [3]="小乔" [5]="安其拉")
注意:
1. 下标可以不连续,可以指定下标,存储时,会按照下标进行排序存储
2. 若下标冲突,元素之间会出现覆盖
删除数组元素
## 1. 删除所有数组元素
unset 数组名
## 2.单独删除某个数组元素
unset 数组名[下标]
标签:shell,##,echo,sh,linux,root,localhost
From: https://blog.csdn.net/buzhi______/article/details/141988063