shell脚本编写-1

1、脚本调试-脚本运行前要进行脚本调试

   bash -n /path/to/some_script 检测脚本中的语法错误

   bash -x /path/to/some_script 调试执行

2、shell是弱类型编程语言

1)、无须指定变量类型,默认为字符型;变量参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用

如:bash 不支持浮点数

  2)变量命名法则

不能使程序中的保留字:例如if, for

只能使用数字、字母及下划线,且不能以数字开头

见名知义

统一命名规则,例如驼峰命名法

3、本地变量

生效范围为当前shell进程,对当前shell 之外的其它shell 进程,包括当前shell 的子shell 进程均无效;

1)、变量赋值:name=‘value’

可以使用引用value:

(1) 可以是直接字串; name=“root"

(2) 变量引用:name="$USER"

(3) 命令引用:name= COMMAND , name =$(COMMAND)

"" :弱引用,其中的变量引用会被替换为变量值

'' :强引用,其中的变量引用不会被替换为变量值,而保持原字符串

2)、变量引用即是引用或者使用变量的值,格式为:${name}, $name;前一种格式较为稳妥

3)、显示已定义的所有变量:set

     删除变量:unset name

4、环境变量:生效范围为当前shell及其子子孙孙shell进程

    变量声明、赋值:

export name=VALUE

declare -x name=VALUE

    变量引用:$name, ${name}

    显示所有环境变量:

export

env

printenv

    删除:unset name

    bash 有许多内建的环境变量:PATH, SHELL, USRE,UID,HISTSIZE,HOME,PWD,OLDPWD,HISTFILE,PS1

5、只读变量:只能声名,但不能修改和删除

readonly name=value

declare -r name=value

6、位置变量:在脚本代码中调用通过命令行传递给脚本的参数

$1, $2, … :对应第1 、第2 等参数(但是地址变量$10指的是第一个参数$1和0的组合,例如$1参数是x,那么$10就是x0)

$0: 命令本身,例如/root/bin/arg.sh

$*: 传递给脚本的所有参数,全部参数合为一个字符串

$@: 传递给脚本的所有参数,每个参数为独立字符串

$#: 传递给脚本的参数的个数

$@ $* 只在被双引号包起来的时候才会有差异

例如f1.sh脚本#!/bin/bash

f2.sh “$*”

f2.sh “$@”

7、算术运算

bash 中的算术运算:

+, -, *, /, % (取余), ** (乘方)

实现算术运算:

(1) let var= 算术表达式

(2) var=$[ 算术表达式]

(3) var=$(( 算术表达式))

(4) echo ‘算术表达式’ | bc

   乘法符号有些场景中需要转义,如*

   bash 有内建的随机数生成器:$RANDOM (1-32767)

echo $[$RANDOM%50] 生成0-49 之间随机数

8、赋值

增强型赋值:+=, -=, *=, /=, %=

   let varOPERvalue

例如:let count+=3,意思是变量count自加3 后自赋值

let var++

let var—

后置加加和前置加加
i++
表示i的值作为表达式的值,然后i自加1
++i
表示i先自加1再作为表达式的值

9、逻辑运算

true, false

      1, 0

 与:

1 与 1 = 1

1 与 0 = 0

0 与 1 = 0

0 与 0 = 0

 或:

1 或 1 = 1

1 或 0 = 1

0 或 1 = 1

0 或 0 = 0

命令true,#true命令执行后#echo $?的返回值是0

命令false,#false命令执行后#echo $?的返回值是非零任意数

短路与&&:exp1 如果为假,exp2就不运算;也是exp1为真,exp2就运算

短路或||:exp1 如果为真,exp2就不运算;也是exp1为假,exp2就运算

异或^:exp1与exp2相同为假,不同为真

10、聚集命令

    有两种聚集命令的方法:

复合式:date; who | wc –l   命令会一个接一个地运行

子shell式 :(date; who | wc -l ) >> /tmp/trace 所有的输出都被发送给单个STDOUT 和STDERR

11、退出状态

进程可以使用退出状态来报告成功或失败

$? 变量保存最近的命令退出状态,可以在脚本中使用,保存的是前一个紧挨着的命令的执行状态

#echo $? 返回值为0代表成功,1-255 代表失败

例如:

#ping -c1 -W1 hostIP &> /dev/null

# echo $?

   (第一条命令中:-c1选项表示ping一次,-W1表示1秒)

12、退出状态码

exit [n]:自定义退出状态码

例如,在脚本中最后一行写入exit 99,则脚本运行结束后,无论脚本倒数第二行的命令成功或者失败,则查看退出状态时#echo $?的返回值都是99

注意:脚本中一旦遇到exit 命令,脚本会立即终止,终止退出状态取决于exit 命令后面的数字,若exit命令后无数字,则终止退出状态码取决于此exit命令前一条命令的执行结果成败取0或者非零的任意数

注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

13、条件测试

测试命令:

test EXPRESSION

[ EXPRESSION ]

[[ EXPRESSION ]],双中括号有更强适用性

注意:若使用第二、三条测试命令,则EXPRESSION 前后必须有空白字符

&&与||是条件性的执行操作符

示例(双引号):

$ test "$A" == "$B" && echo "Strings are equal"

$ test “$A” -eq “$B” && echo "Integers are equal"

简写格式的例子:

$ [ "$A" == "$B" ] && echo "Strings are equal"

$ [ "$A" -eq "$B" ] && echo "Integers are equal"

14、bash 的测试类型

    1)、数值测试:

-gt:  是否大于;

-ge:  是否大于等于;

-eq:  是否等于;

-ne:  是否不等于;

-lt:  是否小于;

-le:  是否小于等于;

     2)、字符串测试:

== :是否等于;

>: ascii码是否大于ascii码

<: 是否小于

!=: 是否不等于

=~: 左侧字符串是否能够被右侧的PATTERN所匹配

(注意:  此上表达式一般用于[[ ]]中)

-z "STRING" :字符串是否为空,空为真,不空为假

-n "STRING" :字符串是否为空,不空为真,空为假

(注意:用于字符串比较时的用到的操作数都应该使用引号)

3)、文件测试

     存在性测试

-a FILE :同-e

-e FILE : 文件存在性测试,存在为真,否则为假;

    存在性及类别测试

-b FILE :是否存在且为块设备文件

-c FILE :是否存在且为字符设备文件

-d FILE :是否存在且为目录文件

-f FILE :是否存在且为普通文件

-h FILE 或 -L FILE :是否存在且为符号链接文件

-p FILE :是否存在且为命名管道文件

-S FILE :是否存在且为套接字文件

文件权限测试:-r、-w、-x

    文件特殊权限测试:

-g FILE :是否存在且拥有sgid 权限

-u FILE :是否存在且拥有suid 权限

-k FILE :是否存在且拥有sticky权限

文件大小测试:

-s FILE:  是否存在且非空,也即非空为真,#[ -s FILE ]执行后#echo $?的返回值是0

    文件是否打开:

-N FILE :文件自上一次被读取之后是否被修改过,也即是atime在mtime前就是自上一次读取后被修改过,#[ -N FILE ]执行后#echo $?的返回值是0

-O FILE :当前有效用户是否为文件属主

-G FILE :当前有效用户是否为文件属组

    双目测试:

FILE1 -ef FILE2: FILE1与FILE2是否指向同一个设备上的相同inode,也即是FILE1与FILE2是否是硬链接的关系,如是为真,不是为假

FILE1 -nt/-ot FILE2: FILE1是否新/旧于FILE2,比较的是FILE1与FILE2的修改时间,也即mtime

15、组合测试条件

    第一种方式:

COMMAND1 && COMMAND2  并且

COMMAND1 || COMMAND2  或者

! COMMAND

如:[ -e FILE ] && [ -r FILE ]

    第二种方式:

EXPRESSION1 -a EXPRESSION2  并且

EXPRESSION1 -o EXPRESSION2  或者

! EXPRESSION

如:# [ -z “$HOSTNAME” -o "$HOSTNAME" =="localhost.localdomain" ] && hostname www.magedu.com

    主机名为空或者是localhost.localdomain,那么就定义主机名为www.magedu.com

# [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

如果/bin/cat是存在且为普通文件并且/bin/cat有执行权限,那么就执行cat /etc/fstab

16、使用read 命令来接受输入

read 从标准输入即键盘输入中读取值,分配给一个或多个shell变量

-p 指定要显示的提示信息

用法:read -p “Enter a filename:” FILE

示例:指定文件做为参数,编写脚本判断文件是否为.sh后缀,如果是,添加x权限;不是,则提示xxf

#!/bin/bash

read -p "please input the file:" a

A1=echo $a | grep -o "\.[^.]\+$"

[[ "$A1" == ".sh" ]] && chmod +x $a || echo xxf

17、脚本example.sh未赋予权限时,使用bash、source及 .

1)、使用bash运行相当于开了一个子shell example.sh,example.sh里面的变量当前终端shell不可引用;

2)、使用source和 .运行example.sh脚本,就相当于直接在当前终端运行脚本example.sh内变量和命令代码,所有example.sh里面的变量可以为当前终端shell引用

所以可知,bash是给脚本用的,source和 .是给配置文件使用的

例如example.sh脚本位于当前root用户的家目录下,为#!/bin/bash

                                                   a=haha

                                                   PATH=/XXX

                                                   echo PATH=$PATH

                                                   cd /tmp

那么如果使用source或者 .来运行脚本example.sh,比如# . /root/example.sh后

输出的结果是PATH=/XXX,同时当前的目录变为/tmp,实际上变量a和PATH是定义于当前终端上了,故而

再#echo $a 的输出结果是haha,而不是为空

  #echo $PATH 的输出结果是/XXX,而不再是默认的PATH路径,因为原先的PATH变量被替换

  #pwd 的返回值是/tmp,而不是当前root用户的家目录/root


原创文章,作者:18612763863,如若转载,请注明出处:/35548

联系我们

400-080-6560

在线咨询:点击这里给我发消息

邮件:1823388528@qq.com

工作时间:周一至周五,9:30-18:30,节假日同时也值班

友情链接:万达主管  万达娱乐招商QQ  万达招商  万达娱乐开户  测试  万达直属  万达娱乐注册  万达主管  万达娱乐主管QQ  万达注册