博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

shell (一)

 

 

 

 

 

 

 

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

 

格式:

1、  export 变量名=values

2、  变量名=values; expoer变量名

3、  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 、$[]

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

执行简单的整数运算,只需将特定的算术表达式用”$(( 和 ))” 括起来

 

 

[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]

 

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

提示:

1、  在[[]]中可以使用通配符进行模式匹配

2、  && 、||、>、< 、等操作符可以应用于[[]]中、单不恩能够应用于[]中

3、  对整数进行关系运算、也可以使用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 和 ||) 、非(!) 将表达式连接起来、接着上面的变量

 

 

 

注意:前面我们已经讲解过了。

1、    “-a”和 “-o” 逻辑操作符号用于[[]]中使用

2、    “&&”和“||”逻辑操作符号用于[[]]中使用

3、    注意括号两端、必须要有空格、

 

 

 

 

大 {} 的使用方法

 

 

 

单条件字符串测试

 

 

多条件字符串测试

 

 

 

[

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

 

双括号里面只对 ||前面的一段取反、如果后面需要取反,需要加一个!(非)

 

EOF 明天更新吧。!!!睡觉去

 

posted @ 2017-11-05 23:08  crazy_py  阅读(469)  评论(0编辑  收藏  举报