shell编程基础:构建基础脚本(1)

内容列表

1. 使用多个命令

方式样式介绍
使用;连接两条命令command1 ; command2第一条失败后,第二条仍然执行
使用&&连接两条命令command1 && command2第一条失败后,第二条不会执行
# 1. 使用;分隔两个命令
[root@vm14 ~]# date ; pwd
2020年 03月 29日 星期日 21:18:41 CST
/root
# 使用;进行分隔的命令,当第一条失败后,第二条仍然会执行
[root@vm14 ~]# date %m ; pwd
date: 无效的日期"%m"
/root

# 2. 使用&&连接
[root@vm14 ~]# date && pwd
2020年 03月 29日 星期日 21:20:31 CST
/root
# 使用&&连接的两条命令,第一条失败后,第二条不会继续执行
[root@vm14 ~]# date %m && pwd
date: 无效的日期"%m"

2. 创建脚本文件

shell脚本第一行内容格式为:#!/bin/bash,用于指定执行脚本所使用的的shell(shell有多种,此处指定使用bash执行)。当然第一行内容可以缺失,执行时会使用用户的默认shell执行。
我们通过vim创建第一个测试脚本/root/shell/test1.sh,内容如下:

#!/bin/bash
# 这一行是注释内容,shell中以#开头的都是注释(不包括第一行shell类型声明)
date
pwd

在目录/root/shell下脚本执行:

# 方式1,使用sh进行执行
[root@vm14 shell]# sh test1.sh 
2020年 03月 29日 星期日 21:36:40 CST
/root/shell


# 方式2,使用相对路径进行执行
[root@vm14 shell]# chmod u+x test1.sh 
[root@vm14 shell]# ./test1.sh 
2020年 03月 29日 星期日 21:40:02 CST
/root/shell


# 方式3,将/root/shell配置到PATH中,然后使用文件名进行调用
# 3.1 将/root/shell加入PATH
cat >> ~/.bash_profile << EOF
PATH=\$PATH:/root/shell
export PATH
EOF
# 3.2 使PATH生效
[root@vm14 shell]# source ~/.bash_profile
# 3.3 查看PATH,如果输出内容包含/root/shell则说明设置成功
[root@vm14 shell]# echo $PATH 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/shell
# 3.4 执行shell(需要进行权限修改)
[root@vm14 shell]# test1.sh 
2020年 03月 29日 星期日 21:50:17 CST
/root/shell


# 方式4,一般情况下~/bin已经被加入到PATH中,也就是我们只需要在~(用户home)下创建bin目录,然后在bin下创建shell脚本便可直接执行

3. 显示消息

# 使用echo将信息显示到控制台,字符串无需用引号(’|")进行标示
[root@vm14 shell]# echo this is a test message
this is a test message
# 当内容有单引号时,用双引号标示字符串
[root@vm14 shell]# echo "this's a ' message"
this's a ' message
# 当内容有双引号时,用单引号标示字符串
[root@vm14 shell]# echo 'this is a "" message'
this is a "" message
# 同时包含时
[root@vm14 shell]# echo "this'"'s a " message'
this's a " message

创建脚本/root/shell/test2.sh,内容如下

#!/bin/bash
# 输出当前时间
echo '当前时间是:'
date

脚本执行:

# 在/root/shell下执行
[root@vm14 shell]# sh test2.sh 
当前时间是:
2020年 03月 29日 星期日 22:08:00 CST
# 上面的输出中描述与时间不在一行,可以将脚本中echo命令第一个参数改成-n使其输出到一行
# echo -n '当前时间是:'
[root@vm14 shell]# sh test2.sh 
当前时间是:2020年 03月 29日 星期日 22:10:59 CST

4. 使用变量

4.1 环境变量

shell维护着一组环境变量,用来记录特定的系统信息。比如系统的名称、登录到系统上的用
户名、用户的系统ID(也称为UID)、用户的默认主目录以及shell查找程序的搜索路径。可以用
set命令来显示一份完整的当前环境变量列表。

[root@vm14 shell]# set 
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
# 省略
USER=root
XDG_RUNTIME_DIR=/run/user/0
XDG_SESSION_ID=17
_=test2.sh
colors=/root/.dir_colors

获取系统变量

# 显示用户名
[root@vm14 shell]# echo 用户名:$USER
用户名:root
# 显示home
[root@vm14 shell]# echo home:$HOME
home:/root
# 转义字符使用,使用\可以使$不再解读为取变量值
[root@vm14 shell]# echo 商品价格:$15
商品价格:5
[root@vm14 shell]# echo 商品价格:\$15
商品价格:$15

4.2 用户变量

# 定义变量
[root@vm14 shell]# var1=第一个变量
[root@vm14 shell]# var2=第二个变量
[root@vm14 shell]# echo $var1
第一个变量
[root@vm14 shell]# echo $var1 $var2
第一个变量 第二个变量

4.3 命令替换

命令替换:将命令执行结果赋值给变量

# 方式1,使用`符号
[root@vm14 shell]# var1=`date`
[root@vm14 shell]# echo $var1
2020年 03月 29日 星期日 22:25:46 CST
# 方式2,使用$()
[root@vm14 shell]# var2=$(date)
[root@vm14 shell]# echo $var2
2020年 03月 29日 星期日 22:26:28 CST

应用示例

# 根据日期生成日志文件
[root@vm14 shell]# touch $(date +%Y%m%d).log
# 查看生成文件
[root@vm14 shell]# ls
20200329.log  test1.sh  test2.sh

命令替换会创建一个子shell来运行对应的命令。子shell( subshell)是由运行该脚本的shell
所创建出来的一个独立的子shell( child shell)。正因如此,由该子shell所执行命令是无法
使用脚本中所创建的变量的。
在命令行提示符下使用路径./运行命令的话,也会创建出子shell;要是运行命令的时候
不加入路径,就不会创建子shell。如果你使用的是内建的shell命令,并不会涉及子shell。
在命令行提示符下运行脚本时一定要留心!

5. 输入输出重定向

5.1 输出重定向

# > 覆盖重定向, command > outputfile
# 将date命令的结果输出到date.log文件中(会覆盖之前内容)
[root@vm14 shell]# date > date.log
[root@vm14 shell]# cat date.log 
2020年 03月 29日 星期日 22:35:03 CST

# >> 追加重定向, command >> outputfile
# 将date命令的结果输出到date.log文件中(不覆盖之前内容)
[root@vm14 shell]# date >> date.log
[root@vm14 shell]# cat date.log 
2020年 03月 29日 星期日 22:35:03 CST
2020年 03月 29日 星期日 22:36:40 CST

5.2 输入重定向

# < 文件输入重定向, command < inputfile
# 计算文件test1.sh的行数、词数、字节数
[root@vm14 shell]# wc < test1.sh 
  4   5 121

# 内联输入重定向( inline input redirection),格式如下
command << marker
data
marker

# 示例:
wc << EOF
TEST 1
TEST 2
TEST3
EOF
# 上例中EOF为使用的marker,可以自己定义,比如定义成 END
wc << END
TEST 1
TEST 2
TEST3
END
# 上面两个效果是一致的

6. 管道

管道:将上个命令的输出,传递给下个命令当做输入。
格式:command1 | command2 ,将command1的输出,传递给command2当做输入

# 将date命令的输出,传递给wc命令作为输入
[root@vm14 ~]# date | wc
      1       6      43
# ps -ef显示全部进程,通过管道传递给grep命令,进行筛选
[root@vm14 ~]# ps -ef |grep ssh
root       6669      1  0 15:23 ?        00:00:00 /usr/sbin/sshd -D
root      62710   6669  0 21:42 ?        00:00:00 sshd: root@pts/0
root      62742  62715  0 21:44 pts/0    00:00:00 grep --color=auto ssh

7. 数学运算

7.1 expr命令

操作符与操作数之间必须要有空格,且仅支持整数运算

# 加法
[root@vm14 ~]# expr 1 + 1
2
# 减法
[root@vm14 ~]# expr 4 - 1
3
# 乘法,需要对*进行转义
[root@vm14 ~]# expr 1 \* 4
4
# 除法
[root@vm14 ~]# expr 4 / 3
1

expr命令支持的所有命令符列表

7.2 方括号

格式:$[num1 操作符 num2],数字与操作符之间空隔可有可无,仅支持整数运算

# 加法
[root@vm14 ~]# echo $[1+2]
3
# 减法
[root@vm14 ~]# echo $[4 -1]
3
# 乘法,不需要对*进行转义
[root@vm14 ~]# echo $[1*4]
4
# 除法
[root@vm14 ~]# echo $[4/3]
1

7.3 bash计算器

bash计算器能够识别

  • 数字(整数和浮点数)
  • 变量(简单变量和数组)
  • 注释(以#或C语言中的/* */开始的行)
  • 表达式
  • 编程语句(例如if-then语句)
  • 函数

7.3.1 bash计算器初试:

# 安装bash计算器
yum install bc
# 使用,命令行中输入bc,然后回车
[root@vm14 ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type 'warranty'. 
# 加法:输入1.1+2.11,然后回车
1.1+2.11
3.21
# 减法:输入4.21-1.1,然后回车
4.21-1.1
3.11
# 乘法:输入1.99*1.21,然后回车
1.99*1.21
2.40
# 除法:输入4/3,然后回车
4/3
1
# 精度问题,上面的除法只保留了整数部分,可以通过scale=4来设置保留4位小数
scale=4
# 重算除法
4/3
1.3333
# 重算乘法
1.99*1.21
2.4079
# 使用quit命令退出
quit

7.3.2 脚本中使用bc

# 示例1,使用$()
[root@vm14 ~]# var1=$(echo 'scale=4; 1.99*1.1'|bc)
[root@vm14 ~]# echo $var1
2.189

# 示例2,使用``
[root@vm14 ~]# echo `echo "scale=4; $var1*$var2"|bc`
2.189

# 示例3 使用内联输入重定向
echo $(bc << EOF
1.99*1.1
EOF
)
# 返回值
2.18

8. 退出脚本

8.1 退出状态码

shell中运行的每个命令都使用退出状态码( exit status)告诉shell它已经运行完毕。退出状态码是一个0~ 255的整数值,在命令结束运行时由命令传给shell。可以捕获这个值并在脚本中使用。

Linux提供了一个专门的变量$?来保存上个已执行命令的退出状态码。

[root@vm14 ~]# date 
2020年 03月 30日 星期一 22:31:09 CST
# 查看date命令的状态码,按照惯例,一个成功结束的命令的退出状态码是0。
[root@vm14 ~]# echo $?
0

# 如果一个命令结束时有错误,退出状态码就是一个正数值。
[root@vm14 ~]# date %m
date: 无效的日期"%m"
[root@vm14 ~]# echo $?
1

Linux退出状态码列表

8.2 exit命令

默认情况下, shell脚本会以脚本中的最后一个命令的退出状态码退出。exit命令允许你在脚本结束时指定一个退出状态码。

自定义状态码示例:
创建脚本/root/shell/test3.sh,内容如下:

#!/bin/bash
# 自定义退出状态码
var1=10
var2=30
var3=$[$var1*$var2]
echo var3 is $var3
# 此处返回300 
exit $var3

执行脚本

[root@vm14 shell]# sh test3.sh 
var3 is 300
# 返回值是44,因为状态码范围是0-255,当返回值val超过这个范围时返回:val % 256 > 0 ? val % 256 : val % 256 +256
# 此处val = 300 , 也就是返回300 % 256 =44
[root@vm14 shell]# echo $?
44


附录:

expr命令符列表:

操作符功能
ARG1 | ARG2如果ARG1既不是null也不是零值,返回ARG1;否则返回ARG2
ARG1 & ARG2如果没有参数是null或零值,返回ARG1;否则返回0
ARG1 < ARG2如果ARG1小于ARG2,返回1;否则返回0
ARG1 <= ARG2如果ARG1小于或等于ARG2,返回1;否则返回0
ARG1 = ARG2如果ARG1等于ARG2,返回1;否则返回0
ARG1 != ARG2如果ARG1不等于ARG2,返回1;否则返回0
ARG1 >= ARG2如果ARG1大于或等于ARG2,返回1;否则返回0
ARG1 > ARG2如果ARG1大于ARG2,返回1;否则返回0
ARG1 + ARG2返回ARG1和ARG2的算术运算和
ARG1 - ARG2返回ARG1和ARG2的算术运算差
ARG1 * ARG2返回ARG1和ARG2的算术乘积
ARG1 / ARG2返回ARG1被ARG2除的算术商
ARG1 % ARG2返回ARG1被ARG2除的算术余数
STRING : REGEXP如果REGEXP匹配到了STRING中的某个模式,返回该模式匹配
match STRING REGEXP如果REGEXP匹配到了STRING中的某个模式,返回该模式匹配
substr STRING POS LENGTH返回起始位置为POS(从1开始计数)、长度为LENGTH个字符的子字符串
index STRING CHARS返回在STRING中找到CHARS字符串的位置;否则,返回0
length STRING返回字符串STRING的数值长度
+ TOKEN将TOKEN解释成字符串,即使是个关键字
(EXPRESSION)返回EXPRESSION的值

Linux退出状态码:

状 态 码描 述
0命令成功结束
1一般性未知错误
2不适合的shell命令
126命令不可执行
127没找到命令
128无效的退出参数
128+x与Linux信号x相关的严重错误
130通过Ctrl+C终止的命令
255正常范围之外的退出状态码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值