shell (一)

作者: print("") 分类: linux 发布时间: 2017-04-21 10:08

Shell脚本简历
1.1什么是shell脚本
在解释shell脚本之前、我们来说下什么shell?
Shell是一个命令解释器、它在操作系统的最外层、负责直接与用户对话、把用户的输入解释给操作系统、并处理各种各样的操作系统的输出结果、输入到屏幕返回给用户、这种对话方式可以是交互式方式、(从键盘输入命令、可以立即得到shell的回应)、或shell非交互脚本方式
1、2什么是shell脚本?
当命令或语句不在命令行执行、而是通过一个程序文件执行时、改程序贝称为shell脚本或sehll程序、shell程序类似于DOS系统下的批处理程序(*.bat)。用户可以在shell脚本输入一系列的命令或命令语句、这些,命令、变量、和流程控制语句等有机会的结合在一起形成了一个功能强大的shell脚本。
 
查看系统shell
[root@mail2 ~]# echo $SHELL
/bin/bash
[root@mail2 ~]#
 
1.3shell脚本的建立
脚本的开头(第一行)、
一个规范的shell脚本的第一行会指出由那个程序(解释器)来执行脚本中的内容、在linux bash编程中,一般为
#!/bin/bash 或者/bin/sh
#!又称作幻数、在执行bash脚本的时候。内核会根据它来指定改用那个程序来解释脚本的内容、这一行必须在脚本顶端的第一行。如果不是第一行则为注释
 
1)开头加版权等信息
#date : 20:40 2017-03-22
#Author : jack ben
#mail  :1249648969@qq.com #Function : This backup mysql is ,,,
#version: 1.1
2)脚本中不用中文注释:
尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰
3) 脚本以 .sh 为扩展名
例如:backup.sh
4)代码书写优秀习惯
1、成对内容的一次写出来,防止遗漏,如:
{}  []  ‘’ “”
2、流程控制语句
If 条件内容
Then
内容
Fi
For循环格式一次完成
For
Do
内容
Done
提示:while和until等循环也是一样的。
  二、shell变量基础及深入 1、变量可分为两类:环境变量(或全局变量) 和局部变量
环境变量也可称作全局变量,也可以在创建它的shell及其派生出来的任意子进程shell中使用、局部变量只能在创建他们的shell函数或脚本中使用、还有一些变量是用户创建的,其他的则是专用的shell变量。
2、环境变量用于定义shell的运行环境、保证shell命令的正确执行、shell通过环境变量来确定登陆用户名,命令路径、终端类型、登陆目录等、所有的环境变量都是系统全局变量。也可以用于所有子进程中、这包括编辑器、shell脚本和各类应用。
3、自定义环境变量(全局变量)
设置环境变量
如果想设置环境变量、就要在给变量赋值之后或设置变量时使用export命令、带-x 选项的declare内置命令也可以完成同样的功能。(注意:输出变量时不要在变量名前面加$)
Export 命令和选项

选项
-f
-n
-p

格式:

  • export 变量名=values
  • 变量名=values; expoer变量名
  • Declare –x 变量名=value

提示:以上为三种设置环境变量的方法
例:
expoer NAME=oldboy
declare –x NAME=oldboy
NAME=oldboy;export NAME
自定义全局变量环境实例:
cat  /etc/profile |grep OLD
export OLDBOY=’oldboy’
让配置生效
. ./etc/profile
后面echo $OLDBOY
 
 
显示系统环境变量
[root@mail2 aa]# env
取消环境变量
[root@mail2 aa]# unset USER
 
三、局部变量
定义本地变量在用户当前的shell生存期的脚本使用。例如,本地变量OLDBOY取值为ett098,这个值只在用户生成器中有意义。如果在shell中启动另一个进程或退出。本地变量OLDBOY值将无效。
普通字符串变量定义。
变量名=values
变量名=’values’
变量名=”vaules”
例1
a=192.168.1.1         无引号
b=’192.168.1.1’        单引号
c=”192.168.1.1”        双引号
echo $a
echo $b
echo $c
答案是:
a=192.168.1.1
b=192.168.1.1
c=192.168.1.1
例子2:
a=192.168.168.1.2-$a     无引号
b=’192.168.168.1.2-$a’     单引号
c=”192.168.168.1.2-$a”     双引号
想想abc什么什么结果
a=192.168.168.1.2-192.168.1.1
b=192.168.1.2-$a
c=192.168.168.1.2-192.168.1.1
为什么会这样呢。
提示:
第一种定义a变量的方式是直接定义变量内容,内容一般为简单连续的数字、字符串、路径
第二种定义b变量的方式是通过单引号定义变量、这个方式的特点是:输入变量时引号里面是什么就输入什么
第三种定义c变量方式是通过双引号定义变量、这个方式的特点是:输出变量时引号里的变量会经过解析后输入改变量内容。而不是把引号中的变量原样输出、适合字符串附带有变量的内容定义。
 
 
 
 
######shell 特殊变量
1、位置变量
$0 获取当前执行的shell脚本的文件名
$n 获取当前执行的shell脚本的第n个参数值、n=1….9 ,当n为0时表示脚本的文件名。如果n大于9,用大括号括起来${10}
$* 获取当前shell的所有参数、$1 $2 $3 …..注意与$#的区别
$# 获取当前shell命令行中参数的总个数
$@ 这个程序的所有参数 “$1” “$2” “$3” “$4”……..
2、进程状态变量
$$ 获取当前sehll的进程号(PID)
$! 执行上一个指令的PID
$? 获取执行的上一个指令的返回值(0为成功,非0为失败)####这个变量很常用
$_ 在此之前执行的命令或脚本的最后一个参数
 
#### 1.4 bash 内部变量
有些内部命令在忙目录列表时是看不见的。他们有shell本身提供,常用的内部命令有:echo、eval、exec、export、readonly、read、shift、exit和点(.)
echo 变量名表
将变量名表指定的变量显示到标准输出
eval args
读入参数args、并将他们组合成一个新的命令、然后执行、
exec 命令参数
当shell执行到exec语句时、不会去创建新的子进程、而是转去执行指定的命令、当指定的命令执行完是、该进程(也就是最初的shell)就会终止、所以shell程序中ecec后面的语句将不会贝执行
Expoer 变量名=value
Shell 可以用export把它的变量向下带入子shell、从而让子进程继承父进程中的环境变量、但子shell不能用expoer把它的变量向上带入父shell
Readonly 变量名
只读变量、用readonly显示所有只读变量
Read 变量名表
从标准输入字符串、传给指定变量、
可以在函数中用local变量名的方式申请局部变量
Shift语句
Shift语句按如下方式重新命名所有的位置参数变量、即$2成为$1,$3 成为$2 在程序中没使用一次shift语句、都使所有的位置参数一次向左移动一个位置、并使位置参数$#减一、直到减到0为止、
echo $1 $2 $3
if [ $2 -eq 2 ]
then
shift
echo $1
fi 执行一下 当$2等于2的时候用shift 就会向前变一位就是$1变为$2
 
#####变量子串常用操作

表达式 说明
${#string} 返回$string的长度
${string:position} 在$string中、从位置$position之后开始提取子串
${string:position:length} 在$string中、从位置$position之后开始提取长度为$length子串
${string#substring} 从变量$string开头开始删除最短匹配$substring子串
${string##substring} 从变量$string开头开始删除最长匹配$substring子串
${string%substring} 从变量$string开头开始删除最短匹配$substring子串
${string%%substring} 从变量$string开头开始删除最长匹配$substring子串
${string/substring/replace} 使用$replace,来代替第一个匹配的$substring
${string/#substring/replace} 使用$replace 前缀匹配$substring,使用$replace来代替匹配$substring
${string/%substring/replace} 使用$replace 后缀匹配$substring,使用$replace来代替匹配$substring

 
例子定义一个变量
# OLDBOY=“ I am oldboy”
[root@mail2 sh]# echo ${OLDBOY}
i am oldboy
用第一个参数返回字符串的长度
[root@mail2 sh]# echo ${#OLDBOY}  ####只要在变量前面加一个#号就行了 返回的结果是11 这个是没有错
现在使用第二个参数
[root@mail2 sh]# echo ${OLDBOY:2}
am oldboy
从第二个字符段开始截图 现在已经截取了从第二个字符串开始截取后面的字符串。
###测试第三个
[root@mail2 sh]# echo ${OLDBOY:2:2}
截取OLDBOY变量字符串从第二个字符开始截取、取两个字符 ####测试第四个
[root@mail2 sh]# echo ${OLDBOY#i}
最短删除i这个字符 已经删除了i这个字符
提示:统一规律:#从开头开始、%从结尾开始的。
批量替换实例 把这个liang删除掉 运行一下脚本
#!/bin/sh
# jack ben facebook:1249648969@qq.com
for file in `ls ./*.jpg`   ###定义file变量 变量的含义是查看本目录下的.jpg 所有文件
do     ####开始fro循环
/bin/mv $file “${file%liang*}.jpg”  #####mv 修改目录下的所有.jpg 文件从头开始删除liang包括后面的所有名称都删除
done ###结束语句
现在从新查看一下、已经成功了 在举例一个例子: 把HTM修改成小写的。
也可以用sed
echo $file|sed ‘s/HTM/htm/g’
如果脚本如下:
#!/bin/sh
for file in `ls ./*.HTML`
do
# mv $file `echo $file|sed ‘s/HTML/html/g’`    ###这个sed 的修改方式
mv $file `echo “${file/%HTML/html}”`       ###这是变量替换的方式
done 已经成功修改了后面的名字。
三、变量的数值计算
变量的数值计算常见的有如下几个命令
(()) 、let 、expr、bc 、$[]

  • (())用法:(此法很常用)

执行简单的整数运算,只需将特定的算术表达式用”$(( 和 ))” 括起来
[root@mail2 sh]# ((a=1+2**2-4%3))
[root@mail2 sh]# echo $a
8
或者 echo $((1+2**2-4%3))
[root@mail2 sh]# ((a=2**16))
[root@mail2 sh]# echo $a
65536
[root@mail2 sh]# echo $((a+=1))   ####就是表示a=a+1
65537
[root@mail2 sh]#
[root@mail2 sh]# echo $((a++))
1
[root@mail2 sh]# echo $a
2
[root@mail2 sh]# a++ 的用法是先输入后面再执行操作
a –也是一样的先输出同样的数值,后面你在查看时会减少一位
也可以做加法运算
[root@mail2 sh]# echo $((100*(100+1)/2))
5050
公式是这样的 Nx(N+1)/2
 
#####
提示:
1、**为幂运算:%为取模运算就是除法当中的取余数)
2、上面涉及到的参数必须为整数(整形)。不能是小数点(符点数)或者字符串、bc命令可以进行浮点数运算、单一般较少用到、
3、echo $((a++)) 和echo $((a–)) 表示输出自身的值、然后在进行++的运算、echo$((++a))
和echo$((–a)) 表示先进行++ — 的运算再输出本身的值
除法运算
[root@mail2 sh]# echo $(( 100 /5))
加法运算
[root@mail2 sh]# echo $(( 100 +5))
减法运算
[root@mail2 sh]# echo $(( 100 -5))
乘法运算
[root@mail2 sh]# echo $(( 100 *5))
平方计算
[root@mail2 sh]# echo $(( 100 **5))
取模法、余数
[root@mail2 sh]# echo $(( 100 %5))
 
#!/bin/sh
a=6
b=2
echo “a-b=$(($a-$b))”
echo “a+b=$(($a+$b))”
echo “a*b=$(($a*$b))”
echo “a/b=$(($a/$b))”
echo “a**b=$(($a**$b))”
echo “a%b=$(($a%$b))” 问题:如何把 a、b 两个变量通过命令行的传参的方式实现
解答 把a修改为=$1
把b修改为=$2 扩展:实现一个加、减、乘、除、等功能的计算器、通过命令行传参的方式实现
  Let用法
格式:
Let赋值表达式
【注】let赋值表达式功能等同于:((赋值表达式))
#i=2
#i=i+8 提示:let i=i+8 等同于((i=i+8)) 后者效率更高
 
expr (evaluate exproressions ) 命令用法
expr 命令一般用于整数值、但也可用于字符串、用来求表达式变量的值、同时expr也是一个手工命令行的计算器、语法:expr Expression
[root@mail2 sh]# expr 2+2
2+2
[root@mail2 sh]# expr 2 + 2
4
[root@mail2 sh]# expr 2 * 2
expr: 语法错误
[root@mail2 sh]# expr 2 \* 2
4
[root@mail2 sh]# expr 2 % 2
0
[root@mail2 sh]# expr 10 % 2
0
[root@mail2 sh]#
提示:
1):注意运算符左右都有空格
2、使用乘号是、必须用反斜线屏蔽其特定含义、因为shell可能会误解星号的含义
可以用expr $[$a+$b]表达式形式、$a $b 可为整数
[root@mail2 ~]# expr $[2+2]
4
[root@mail2 ~]# 其他特殊的用法:
Expr用法 ssh-copy-id
if expr “$1” : “.*\.pub”; then’
 
 
bc 命令的用法
支持小数级的运算
echo 3.5+5|bc
[root@mail2 ~]# echo 37.8+56.8|bc
94.6
[root@mail2 ~]# [root@mail2 ~]# echo “3.145*3.145″|bc
9.891
[root@mail2 ~]#
如何保留小数点的第一位呢?
[root@mail2 ~]# echo “scale=1;5.23/3.13″|bc
1.6
[root@mail2 ~]#
这个scale 只能使用于除法,不能使用与乘法
转换进制
[root@mail2 ~]# echo “obase=2;8″|bc    ####10进制8转换成2进制
1000
 
[root@mail2 ~]# echo “obase=16;20″|bc   #####10进制20转换为16进制
14 $[] 运算例子
[root@mail2 ~]# echo $[2+2]
4
Shell变量的输出
Shell变量除了可以直接赋值外、还可以使用read命令从标准输入获取
Read 语法格式
read [参数] [变量名]
常用参数:
-p prompt:设置提示信息
-t timeout 设置输入等待的时间、单位默认为秒
[root@mail2 ~]# read -t 5 -p “weloce input tow nuber:” a1 a2
weloce input tow nuber:
如果使用read的方式做一个加减乘除的方法
#!/bin/sh
read -t 5 -p “input two number” a b
echo “a-b=$(($a-$b))”
echo “a+b=$(($a+$b))”
echo “a*b=$(($a*$b))”
echo “a/b=$(($a/$b))”
echo “a**b=$(($a**$b))”
echo “a%b=$(($a%$b))”
利用read的方式写入$a $b 也可以使用这种方法 四、条件测试
条件测试语法
在bash的各种流程控制结构中通常需要进行各种测试、然后根据测试结果执行不同的操作、有时也会通过与if等条件语句相结合、使我们可以方便完成判断。
语法说明:
格式1:test<测试表达式>
格式2:[<测试表达式>]
格式3:[[<测试表达式>]]
说明:
格式1和格式2是等价的
格式3为扩展的test命令、有网友推荐用格式3、个人推荐格式2
提示:

  • 在[[]]中可以使用通配符进行模式匹配
  • && 、||、>、< 、等操作符可以应用于[[]]中、单不恩能够应用于[]中
  • 对整数进行关系运算、也可以使用shell的算术运算符(())

语法例子:
格式1:test<测试表达式>
[root@mail2 sh]# test -f file && echo true||echo false
false
[root@mail2 sh]# touch file
[root@mail2 sh]# test -f file && echo true||echo false
true
测试这个file文件是否存在。如果存在输出true 如果不存在输出false
test 命令非(!)的写法    非的意思就是后面是真就为假。如果是假就是真 格式2 [<表达式>]
[root@mail2 sh]# [ -f file ] && echo 1||echo 0
0
[root@mail2 sh]# touch file
[root@mail2 sh]# [ -f file ] && echo 1||echo 0
1 如果加上非就是为0 格式3 [[<表达式>]] 4.2文件测试操作符
在书写测试表达式时、可以使用表中的文件测试操作符

常用文件测试操作符号 说明
-f 普通文件 若文件存在且为普通文件则为真
-d 文件目录 若文件存在且为目录则为真
-s 文件 若文件存在且不为空(文件大小非0)则真
-e 文件 若文件存在则为真
-r 文件 若文件存在且可读则真
-w 文件 若文件存在且可写则真
-x 文件 若文件存在且为链接文件则真
fl –nt f2 若文件f1比文件f2新则为真
fl –ot f2 若文件f1比文件旧则为真
-n 长度不为0则为真
-z 长度为0则真

 
字符串测试操作符
字符串测试操作符的作用:比较两个字符是否相同、字符串长度是否为零、字符串是否为null(注:bash区分零长度字符串和空字符串)
“=” 比较两个字符串是否相同,与==等价、如if[“$a” =”$b”],其中$a最好用、用“”括起来,因为如果中间有空格等就会出错、当然最好的方法就是if [“${a}”=”${b}”]。
“!=” 比较两个字符串是否相同、可以使用下面的表的字符串测试操作符

常用字符串测试操作符 说明
-z “字符串” 若串长度为0则真 –z 可以理解为zero
-n “字符串” 若串长度不为0则真 –n 可以理解为no zero
“串1”=“串2” 若串1等于串2则真、可以用用==代替=

“串1”!=“串2”                                       若串1不等于串2则真
注意说明:以上表格中字符串测试操作符号要用“”引起来
字符串测试操作提示:
1)-n 比较字符串长度是否不为零、如果不为零则为真如[-n “$myvar”]
2) –z 比较字符串长度是否为零、如果不为零则为真如 [-n “$myvar”]
整数二元比较操作符
在书写测试表达式时、可以时候能用下面的表中的整数二元比较操作符

在[]中使用的比较符号、 在(())和[[]]中使用的比较 说明
-eq == Equal缩写、相等
-ne != Not equal的缩写、不相等
-gt > 大于 great than
-ge >= 大于等于 great equal
-lt < 小于类似 less than
-le <= 小于等于 less equal

提示:
1)“<” 符号意思是小于,if[[“$a”<”$b”]], if[“$a”\<”$b”]。在单[]中需要转义、因为shell也会<和>重定向
2)“>”符号意思是大于if[[“$a”>”$b”]], if[“$a”\>”$b”]。在单[]中需要转义、因为shell也会<和>重定向
3)”=” 符号意思是等于if[[“$a”=”$b”]], if[“$a”=”$b”]。在单[]中不需要转义
特别提示:
经过实践: = 和!= 在[]中不需要使用转义、包含< 、> 的符号在[]中使用需要转义、对于数字不转义的结果未必会报错、但是结果可能不对。
范例:二元数字比较 但是还是返回了1 说明这个是有问题的,尝试一下转义的情况
  转义之后就是正确的了。说明在[] 中< > 是需要使用转义的。
也可以使用 lt 和gt 是使用方法 等号和不等号是不受影响的 范例2:二元字符比较 4.3逻辑操作符
在书写测试表达式时、可以使用如下表中的逻辑操作符实现复杂条件测试

在[]中使用的逻辑操作符 在[[]]中使用的逻辑操作符 说明
-a && 与,两端都为真、则真
-o || 或、两端有一个为真则真
非、相反则为真

提示:
!中文的意思是反:与一个逻辑值相反的逻辑值
-a 中文的意思是与(and &&) 两个逻辑值都为真,返回值为真、反之为假
-o 中文的意思是或(of ||)两个逻辑值只要有一个为真、返回值就为真
逻辑操作符运算规则
真1 假0   and符相当于乘法一样的
And 1*0=0 假
And 1*1=1 真
And 0*0=0 假
两端都是1才为真
Or 或    or相当于加法一样的
Or 1+0=1 真
Or 0+0=0 假
Or 0+1=1 真
 
 
条件测试举例
下面举一些条件测试的例子,为了清晰的显示测试结果、我们屏幕上输出1(表示真)或0(表示假)
提示:这和前面的状态变量:“$?”返回0为真不一样的。 1、以上两条语句功能相同的
2、变量$file 加了双引号、这是编程的好习惯、可以防止很多意外的错误发生、
文件测试举例
定义file1 和file2 两个变量,并分别赋予两个系统文件名的值 多条件文件测试:
可用 与(-a 和&&) 、或(-o 和 ||) 、非(!) 将表达式连接起来、接着上面的变量 注意:前面我们已经讲解过了。

  • “-a”和 “-o” 逻辑操作符号用于[[]]中使用
  • “&&”和“||”逻辑操作符号用于[[]]中使用
  • 注意括号两端、必须要有空格、
  • 大 {} 的使用方法
  • 单条件字符串测试‘
  • 多条件字符串测试
  • [root@mail2 sh]# [[ -z “$file1” && -z “$file2”  ]] && echo 1[root@mail2 sh]# [[ -z “$file1” || -z “$file2”  ]] && echo 1
    [root@mail2 sh]#
    [root@mail2 sh]# [[ -z “$file1” || -z “$file2”  ]] && echo 1 ||echo 0
    0
    [root@mail2 sh]# [[ -z “$file1” || -z “$file2”  ]] && echo 1 ||echo 0
    0
     
     
    [root@mail2 sh]# [ “$file1” = “$file2” ] && echo 1 ||echo 0
    0
    [root@mail2 sh]# [ “$file1” != “$file2” ] && echo 1 ||echo 0
    1
    [root@mail2 sh]#
    整数的二元比较
  • 整数比较大小是否会通过字符串的大小对比吗?测试
  • 测试发现整数的比较是比较它的数字大小。而不是对比字符串的多少 
     
    逻辑操作符举例
    #!/bin/sh
    echo –n “请输入两个数字[格式为:m n]”;
    read m n
    ###第一种写法
    if [ ${m} –eq 1] && [ ${n} –eq 2 ];then
    echo “good”
    else
    echo “bad”
    fi
    #####第二种写法
    if [ ${m} –eq –a ${n} –eq 2 ];then
    echo “good”
    else
    echo “bad”
    fi
    ####第三种写法
    if  [[ ${m} –eq 1 && ${n} –eq 2 ]];then
    echo “good”
    else
    echo “bad”
    fi
     
    && 和-a 与逻辑符写法总结如下:
    echo –n “请 输入两个字母或者任意单词[格式为 :a b]”;
    read a  b
    ###第一种写法
    if [ “${a}” = “a” ] && [ “${b}” =  “b” ];then
    ###第二种写法
    if [  “${a}”= a –a “${b}” = “b” ];then
    ##第三种写法
    if [[ “${a}” = “a” –a “${b}” =”b” ]];then
    ###下面写法不对
    if (( “${a}” = “a” –a “${b}” =”b” ));then
    echo “good”
    else
    echo “bad”
    fi
    需要把-a 改成 &&
    范例2: || 和 –o或 逻辑符
    [[ -z “$file1” || -z “$file2” ]]  && echo 1 || echo 0
     
    [ -z “$file1” -o -z “$file2” ]  && echo 1 || echo 0
    范例三:!非逻辑符
    [ ! “$file1” = “$file2” ] && echo 1 || echo 0
    单括号里面是对整个表达式的取反
    [[ ! –z ”$file1” ||  !-n “$file2” ]] && echo 1 || echo 0
    双括号里面只对 ||前面的一段取反、如果后面需要取反,需要加一个!(非)

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

说点什么

avatar
  Subscribe  
提醒