shell脚本编程初步–吐血整理

shell脚本编程

编程基础

程序:

程序的构成:指令 + 数据

程序的编程风格:

    过程式:以指令为中心,数据服务于指令

    对象式:以数据为中心,指令服务于数据

shell程序:提供了编程能力,解释执行

shell,perl,python语言均为高级编程语言

编程的逻辑处理方式:

    顺序执行

循环执行

选择执行

shell编程:过程式、解释执行

 

脚本基本格式

shell脚本是包含一些命令或声明,并符合一定格式的文本文件

格式要求:首行shabanng机制

#!/bin/bash

#!/usr/bin/python

#!/usr/bin/perl

 

shell脚本用途:

自动化常用命令

执行系统管理和故障排除

创建简单的应用程序

处理文本或文件

 

如何创建shell脚本

第一步:使用文本编辑器来创建文本文件

        第一行必须为shell声明序列,即shebang

            例如:#!/bin/bash

        添加注释:

            注释以#开头(以#开头的行不会被执行)

第二步:运行脚本

        给予执行权限,在命令执行上指定脚本的绝对或相对路径

        运行解释器,将脚本作为解释器程序的参数运行

   

#!/bin/bash

#author: wang

#Version: 1.0

#Description:This script displays some information about your# environment echo "Greetings. The date and time are $(date)" echo "Your working directory is: $(pwd)"

 

脚本调试:

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

bash –x /path/to/some_script:调试执行

 

变量

变量即是命名的内存空间

bash变量为弱类型变量

      即无需指定类型,默认均为字符型;参与运算会自动进行隐式类型转换,变量无需实现定义,可直接调用

变量命名法则:

1、不能使用程序中保留字,如if,for…

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

3、见名知义

4、统一命名法则:驼峰命名法

 

根据变量的生效范围等标准可做以下归类:

   本地变量:生效范围为当前shell进程

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

   局部变量:生效范围为当前shell进程中某代码片段(通常为函数)

   位置变量:$1、$2…,用于表示脚本代码中调用命令行的参数

   特殊变量:$?à 前一条命令的执行结果,0表示成功,1-255表示失败

             $0à 命令本身

             $#à 参数的数量

 

本地变量:

变量赋值:name=‘value’,

可以使用引用value:

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

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

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

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

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

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

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

删除变量:unset name

 

环境变量:

变量声明、赋值:

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

 

只读和位置变量:

 

只读和位置变量

只读变量:只能声时,但不能修改和删除

readonly name

declare -r name

一般是常量中会使用

declare –rx name 表示既是一个常量又是一个环境变量

但是随shell进程终止而终止

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

$1, $2, …:对应第1、第2等参数,shift [n]换位置

$0: 命令本身

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

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

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

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

 

运算

算术运算:

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

实现算术运算:

(1) let var=算术表达式

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

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

(4) var=$(expr arg1 arg2 arg3 …)

(5) declare –i var= 数值

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

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

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

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

如果要表示2-51:echo $[$RANDOM%50+2]

表示1-n: echo $[$RANDOM%N+1]

赋值

增强型赋值:

+=, -=, *=, /=, %=

let varOPERvalue

例如:let count+=3

自加3后自赋值

自增,自减:

let var+=1

let var++

let var-=1

let var–

 

逻辑运算

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

非:!

! 1 = 0

! 0 = 1

短路运算:

短路与:

第一个为0,结果必定为0;

第一个为1,第二个必须要参与运算;

短路或:

第一个为1,结果必定为1;

第一个为0,第二个必须要参与运算;

异或:^

异或的两个值,相同为假,不同为真

 

例如:

#command1 && command2

command1为“假”,则command2 不会再执行

否则,command1为“真”,则command2必须执行

#command1 || command2

command1为“假”,则command2 必须执行

否则,command1为“真”,则command2不会再执行

要实现user1用户不存在就添加用户user1

id user1 || useradd user1

 

 

退出状态

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

0 代表成功,1-255代表失败

$? 变量保存最近的命令退出状态

例如:

ping-c1-W1hostdown&>/dev/null

echo$?

退出状态码

bash自定义退出状态码

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

注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字

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

 

 

 

条件测试

判断某需求是否满足,需要由测试机制来实现;

专用的测试表达式需要由测试命令辅助完成测试过程;

评估布尔声明,以便用在条件性执行中

若真,则返回0

若假,则返回1

测试命令:

test EXPRESSION

[ EXPRESSION ]

[[ EXPRESSION ]]

注意:EXPRESSION前后必须有空白字符

 

条件性的执行操作符

根据退出状态而定,命令可以有条件地运行

&& 代表条件性的AND THEN

 

|| 代表条件性的OR ELSE

例如:

grep-qno_such_user/etc/passwd ||echo'Nosuchuser'

Nosuchuser

ping-c1-W2station1&>/dev/null >&& echo"station1isup" || (echo'station1isunreachable';exit1)

station1isup

test命令

长格式的例子:

test "$A"=="$B" && echo "Stringsareequal"

test "$A" -eq "$B" && echo "Integersareequal"

简写格式的例子:

[ "$A" == "$B" ] && echo "Stringsareequal"

[ "$A" -eq "$B" ] && echo "Integersareequal"

数值测试:

-gt:是否大于;

-ge:是否大于等于;

-eq:是否等于;

-ne:是否不等于;

-lt:是否小于;

-le:是否小于等于;

字符串测试:

==:是否等于;

>:ascii码是否大于ascii码

<:是否小于

!=:是否不等于

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

 

注意:此表达式一般用于[[ ]]中;

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

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

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

 

文件测试

存在性测试

-a FILE:同-es

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

存在性及类别测试

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

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

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

-f FILE:是否存在且为普通文件;(存在为真)

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

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

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

文件权限测试:

-r FILE:是否存在且可读

-w FILE: 是否存在且可写

-x FILE: 是否存在且可执行

 

文件特殊权限测试:

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

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

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

文件大小测试:

-s FILE:是否存在且非空;

非空为真,空为假

文件是否打开:

-t fd:fd表示文件描述符是否已经打开且与某终端相关

-N FILE:文件自上一次被读取之后是否被修改过(读先发生,写后发生)

就是读的时间比较旧

 

双目测试:

FILE1 –ef  FILE2: FILE1与FILE2是否指向同一个设备上的相同inode(硬链接)

FILE1 –nt  FILE2: FILE1是否新于FILE2;(修改的时间)

FILE1 –ot  FILE2: FILE1是否旧于FILE2;(修改的时间)

组合测试条件

第一种方式:

COMMAND1 && COMMAND2 并且

COMMAND1 || COMMAND2 或者

! COMMAND

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

第二种方式:

EXPRESSION1 -a EXPRESSION2 并且

EXPRESSION1 -o EXPRESSION2 或者

! EXPRESSION

必须使用测试命令进行,即进行test或者[ ];

 

意思是只要主机名没有定义或者主机名为默认就改为www.magedu.com

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

 

判断/bin/cat是否为可执行文件,如果是就调用

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

 

使用read命令来接受输入

使用read来把输入值分配给一个或多个shell变量:

-p:指定要显示的提示

-t:TIMEOUT

read从标准输入中读取值,给每个单词分配一个变量

所有剩余单词都被分配给最后一个变量

read -p “Enter a filename:“ FILE

条件选择if语句

选择执行

注意:if语句可嵌套

单分支

if 判断条件:then

条件为真的分支代码

fi

双分支

if 判断条件; then

条件为真的分支代码

else

条件为假的分支代码

fi

多分支

if CONDITION1; then

if-true

elifCONDITION2; then

if-ture

elifCONDITION3; then

if-ture

else

all-false

fi

逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句

 

条件判断:case语句

case 变量引用in

PAT1)

分支1

;;

PAT2)

分支2

;;

*)

默认分支

;;

esac

   

case支持glob风格的通配符:

*:任意长度任意字符

?:任意单个字符

[]:指定范围内的任意单个字符

a|b:a或b


练习:

1、写一个脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息

代码:

[root@localhost bin]# cat creatuser.sh

#!/bin/bash

 

echo "Please input a username:"

read username

id $username &> /dev/null

if [[ $? -eq 0 ]];then

    echo "用户已存在"

else

    useradd $username;echo "用户$username添加成功"

    id $username

fi

测试:

[root@localhost bin]# creatuser.sh

Please input a username:

wang

用户已存在

[root@localhost bin]# creatuser.sh

Please input a username:

li

用户li添加成功

uid=1007(li) gid=1007(li) groups=1007(li)

 

2、写一个脚本/root/bin/yesorno.sh,提示用户输入yes或no,并判断用户输入的是yes还是no,或是其它信息

代码:

[root@localhost bin]# cat yesorno.sh

#!/bin/bash

read -p "Please input yes or no:" x

case $x in

[Yy][Ee][Ss]|[Yy])

    echo you have inputde yes

;;

[Nn][Oo]|[Nn])

    echo you have inputed no

;;

*)

    echo illegal input

;;

esac

测试:

[root@localhost bin]# yesorno.sh

Please input yes or no:yes

you have inputde yes

 

[root@localhost bin]# yesorno.sh

Please input yes or no:Yes

you have inputde yes

 

[root@localhost bin]# yesorno.sh

Please input yes or no:no

you have inputed no

 

[root@localhost bin]# yesorno.sh

Please input yes or no:No

you have inputed no

 

[root@localhost bin]# yesorno.sh

Please input yes or no:aa

illegal input

 

3、写一个脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)

代码:

[root@localhost bin]# cat filetype.sh

#!/bin/bash

 

echo "请输入一个文件路径"

read file

if [[ -L $file ]];then

    echo $file 是一个符号链接文件

elif [[ -f $file ]];then

    echo $file 是一个普通文件

elif [[ -b $file ]];then

    echo $file 是一个块设备文件

elif [[ -c $file ]];then

    echo $file 是一个字符设备文件

elif [[ -d $file ]];then

    echo $file 是一个目录文件

elif [[ -p $file ]];then

    echo $file 是一个管道文件

elif [[ -S $file ]];then

    echo $file 是一个套接字文件

else

    echo No such file

fi

测试:

[root@localhost bin]# filetype.sh

请输入一个文件路径

/etc/rc1.d

/etc/rc1.d 是一个符号链接文件

[root@localhost bin]# filetype.sh

请输入一个文件路径

/etc/issue

/etc/issue 是一个普通文件

[root@localhost bin]# filetype.sh

请输入一个文件路径

/testdir

/testdir 是一个目录文件

[root@localhost bin]# filetype.sh

请输入一个文件路径

/run/systemd/notify

/run/systemd/notify 是一个套接字文件

[root@localhost bin]# filetype.sh

请输入一个文件路径

/dev/sda

/dev/sda 是一个块设备文件

[root@localhost bin]# filetype.sh

请输入一个文件路径

/dev/null

/dev/null 是一个字符设备文件

[root@localhost bin]# filetype.sh

请输入一个文件路径

/dev/zero

/dev/zero 是一个字符设备文件

 

4、写一个脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数

[root@localhost bin]# cat checkini.sh

代码:

#!/bin/bash

 

echo "Please input a number"

read num

if [[ -z $num ]];then

    echo "至少要输入一个数值"

exit

fi

 

NUM=$(echo $num |egrep -o '^\-?[[:digit:]]+$')

if [[ $num == $NUM ]];then

 

   if [[ $num -gt 0 ]];then

    echo $num 是一个正整数

   elif [[ $num -eq 0 ]];then

    echo 输入的是0

   else

    echo $num 是一个负整数

   fi

 

else

    echo $num 不是一个整数

fi

测试:

[root@localhost bin]# checkini.sh

Please input a number

0

输入的是0

[root@localhost bin]# checkini.sh

Please input a number

1

1 是一个正整数

[root@localhost bin]# checkini.sh

Please input a number

-8

-8 是一个负整数

[root@localhost bin]# checkini.sh

Please input a number

sss

sss 不是一个整数

原创文章,作者:Mr.Lee,如若转载,请注明出处:http://www.178linux.com/36625

(0)
Mr.LeeMr.Lee
上一篇 2016-08-18
下一篇 2016-08-18

相关推荐

  • mv命令总结

    mv命令是move的缩写,可以用来移动文件或者将文件改名,是Linux系统下常用的命令,经常用来备份文件或者目录。 命令格式:mv  源文件或目录 目标文件或目录 2.命令功能:视mv命令中第二个参数类型的不同(是目标文件还是目标目录),mv命令将文件重命名或将其移至一个新的目录中。当第二个参数类型是文件时,mv命令完成文件重命名,此时,源文件只能…

    2017-07-24
  • Linux基础小模块

    1.基础知识小块:shell 由shell程序的自带命令:即为内置命令(builtin) 独立的可执行程序文件、文件名 :即为外部命令  [root@localhost~]#ls      ~用户当前所在目录  #:命令提示符(管理员帐号root)  $:普通用户   &nbsp…

    Linux干货 2016-08-10
  • Bash快捷键

    Ctrl + a :移到命令行首Ctrl + e :移到命令行尾Ctrl + f :按字符前移(右向)Ctrl + b :按字符后移(左向)Alt + f :按单词前移(右向)Alt + b :按单词后移(左向)Ctrl + xx:在命令行首和光标之间移动Ctrl + u :从光标处删除至命令行首Ctrl + k :从光标处删除至命令行尾Ctrl + w :…

    Linux干货 2017-03-26
  • 权限命令总结

    修改文件权限:chmod 1 2 3 4 [root@centos7 ~]# man chmod        chmod [OPTION]… MODE[,MODE]… FILE…    …

    Linux干货 2016-08-04
  • 第三周 用户和组管理

    1、列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可。 [root@localhost ~]# who root     pts/0        2017-12-16 22:46 (192.168.43.233) root     pts/1        2017-12-16 22:46 (192.168.43.233…

    2017-12-16
  • (一)Linux发行版及基础命令简述

    计算机 Linux 发行版 命令 帮助

    2017-12-11

评论列表(1条)

  • 马哥教育
    马哥教育 2016-08-19 15:17

    博客作业要按时完成,压得太多,你就越不想写了。