Shell编程规范与变量


前言

Shell是Linux系统中一种特殊程序,在用户终端与内核进行交互的翻译官,用户登录Linux系统时,会自动加载一个Shell程序,离开Shell操作系统将无法运行,Bash是Linux系统中默认的Shell程序。
Shell运行的过程:计算机接收用户所传输的命令,Shell会自动加载,将所接受到的命令转换成计算机所能识别的二进制语言,再将命令传递给系统内核执行。

一、Shell脚本的概述

在一些复杂的Linux维护工作中,大量重复性的输入和交互操作不但费时费力,而且容易出错,而编写一个恰到好处的shell脚本,可以批量处理、自动化地完成一系列维护任务,大大减轻管理员的负担

1.Shell脚本的概念

将要执行的命令按顺序保存到一个文本文件
给该文件可执行的权限
可结合各种Shell控制语句已完成更复杂的操作

2.Shell脚本应用场景

重复性操作
交互性任务
批量事务处理
服务运行状态监控
定时任务执行

3.Shell脚本的构成

1.脚本申明(解释器):若第一行为“#!/bin/bash”,表示此行以下的代码语句是通过/bin/bash程序来解释执行,#!/bin/bash为默认解释器。还有其它类型的解释器,比如#!/usr/bin/python、#!/usr/bin/expect。

2.注释信息:以“#”开头的语句表示为注释信息,被注释的语句在运行脚本时不会被执行。

3.可执行语句

修改这个文件的权限使它可以执行 # 使用 chmod +x + 脚本文件
检测语法错误
执行脚本

3.1 查看当前系统支持的Shell脚本种类

[root@yzq opt]# cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh

3.2 创建一个脚本文件

[root@yzq opt]# mkdir shell_bianliang
[root@yzq opt]# ls
1.txt  rh  shell_bianliang  tar.1.txt.gzip
[root@yzq opt]# cd shell_bianliang/
[root@yzq shell_bianliang]# ls
[root@yzq shell_bianliang]# vim demo.sh

在这里插入图片描述

3.3 执行Shell脚本

方法一:指定路径的命令,要求文件必须有 x 权限。

方法二:指定Shell来解释脚本,不要求文件必须有 x 权限。
sh 脚本路径:(shell脚本调试,将运行过程展示)

[root@yzq shell_bianliang]# sh -x demo.sh 
+ mkdir -p /opt/ky21/id
+ touch /opt/ky21/id/xh.txt
+ echo 14

source 脚本路径:(全局生效,不建议与exit一起使用)

赋予执行权限
执行命令

[root@yzq shell_bianliang]# chmod +x demo.sh 
[root@yzq shell_bianliang]# ./demo.sh 

3.4查看结果

[root@yzq shell_bianliang]# cd /opt/
[root@yzq opt]# ls
1.txt  ky21  rh  shell_bianliang  tar.1.txt.gzip
[root@yzq opt]# cd ky21/
[root@yzq ky21]# ls
id
[root@yzq ky21]# cd id/
[root@yzq id]# ls
xh.txt
[root@yzq id]# cat xh.txt 
14

4 管道和重定向

4.1 管道

将管道符号“|”左侧的命令输出的结果,作为右侧命令的输入(处理对象),同一行命令中可以使用多个管道。
cmd1 命令1 | cmd2 命令2 【…|cmdn 命令n】

统计连接数

[root@yzq ~]# netstat -natp | wc -l
20

4.2 重定向

1.交互式硬件设备
类型设备文件文件描述编号默认设备描述
标准输入/dev/stdin0键盘从该设备接收用户输入的数据
标准输出/dev/stdout1显示器通过该设备向用户输出数据
标准错误输出/dev/stderr2显示器通过该设备报告执行出错信息
2.重定向操作

重定向输入 < 从指定的文件读取数据

[root@yzq opt]# echo "123456" > pass.txt
[root@yzq opt]# cat pass.txt 
123456
[root@yzq opt]# passwd --stdin zhangsan < pass.txt
更改用户 zhangsan 的密码 。
passwd:所有的身份验证令牌已经成功更新。

重定向输出 > 将标准输出结果 保存 到指定的文件,并且覆盖原有内容
>> 将标准输出结果 追加 到指定的文件的尾部,不覆盖原有内容

[root@yzq opt]# cat txt 
111
[root@yzq opt]# echo "222" > txt 
[root@yzq opt]# cat txt 
222
[root@yzq opt]# echo "333" >> txt 
[root@yzq opt]# cat txt 
222
333

标准错误输出 2> 将错误信息 保存 到指定的文件,并且覆盖原有内容
2>> 将错误信息 追加 到指定的文件的尾部,不覆盖原有内容

[root@yzq opt]# aaa
bash: aaa: 未找到命令...
[root@yzq opt]# aaa 2> txt 
[root@yzq opt]# cat txt 
bash: aaa: 未找到命令...
[root@yzq opt]# bbb
bash: bbb: 未找到命令...
[root@yzq opt]# bbb 2>> txt 
[root@yzq opt]# cat txt 
bash: aaa: 未找到命令...
bash: bbb: 未找到命令...

混合输出 &> 将标准输出、标准错误保存到同一文件中
2>&1 将标准错误输出重定向到标准输出

[root@yzq opt]# ls &> txt 
[root@yzq opt]# cat txt 
pass.txt
passwd.txt
rh
shell_bianliang
txt
[root@yzq opt]# ccc &> txt 
[root@yzq opt]# cat txt 
bash: ccc: 未找到命令...
相似命令是: 'cc'
[root@yzq opt]# ccc &>> txt 
[root@yzq opt]# cat txt 
bash: ccc: 未找到命令...
相似命令是: 'cc'
bash: ccc: 未找到命令...
相似命令是: 'cc'

cat
cat <同cat效果相同,但打开方式不同,cat是自己打开自己拿,cat <是重定向输入打开给cat查看

[root@yzq opt]# cat sum.sh 
#!/bin/bash
read -p "输入第一个整数:" num1
read -p "输入第二个整数:" num2
echo "$num1 + $num2的和为:$[$num1+$num2]"
[root@yzq opt]# cat <sum.sh 
#!/bin/bash
read -p "输入第一个整数:" num1
read -p "输入第二个整数:" num2
echo "$num1 + $num2的和为:$[$num1+$num2]"

cat << EOF
EOF为结束符,在输出EOF后cat输出结束并打印出来

[root@yzq opt]# cat <<EOF
> 123
> 456
> EOF
123
456

cat << EOF > txt
可以把输入重定向和输出重定向结合使用,把从屏幕输出的内容保存到文件

456
[root@yzq opt]# cat << EOF > txt
> [local]
> name=local
> baseurl=fire:///mnt
> enabled=1
> gpg
> EOF
[root@yzq opt]# cat txt
[local]
name=local
baseurl=fire:///mnt
enabled=1
gpg

二、Shell脚本变量

变量的分类
自定义变量:由用户自己定义、修改和使用
环境变量:由系统维护,用于设置工作环境
位置变量:通过命令行给脚本程序传递参数
预定义变量:Bash中内置的一类变量,不能直接修改

查看变量的值
格式:echo $变量名
"="表示赋值

1. 自定义变量

自定义变量只在此shell环境生效
由用户自己定义、修改和使用
格式:变量名=变量值
变量名:零时存放数据的地方;字母、数字、下划线组成,不能以数字开头,并且区分大小写
不能是特殊符号
变量值:零时的可变化数据
等号:表示赋值关系
用echo查看和引用变量值
{}引用变量

[root@yzq opt]# a=10
[root@yzq opt]# echo $a
10
[root@yzq opt]# test=100
[root@yzq opt]# echo $testRMB

[root@yzq opt]# echo ${test}RMB
100RMB

echo选项:
-n表示不换行输出

[root@yzq opt]# echo -n $test 
100[root@yzq opt]# 

-e输出转义字符,将转义后的字符输出到屏幕上
常见转义字符:
\c 不换行输出,\c后不存在字符时相当于-n

[root@yzq opt]# echo -e "nihao"
nihao
[root@yzq opt]# echo -e "nihao\c"
nihao[root@yzq opt]# 

\n 表示换行(相当于回车)

nihao[root@yzq opt]# echo -e "nihao\n123"
nihao
123

\t表示转义后插入tab,即制表符

[root@yzq opt]# echo -e "nihao\t123"
nihao	123

注:\转义符,跟在转义符\之后的特殊符号将失去特殊含义,变为普通字符。如$输出$符号,而不是变量

[root@yzq opt]# echo $test
100
[root@yzq opt]# echo \$test
$test

取消定义
unset 变量名

[root@yzq opt]# echo $test
100
[root@yzq opt]# unset test 
[root@yzq opt]# echo $test

[root@yzq opt]# 

2.环境变量

由系统维护,用于设置工作环境

[root@yzq opt]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

使用env命令查看当前环境下的环境变量。
HOME表示用户宿主目录,RANDOM表示随机数。返回0-32767的整数,PWD表示当前所在工作目录。

[root@yzq opt]# env
XDG_SESSION_ID=2
HOSTNAME=yzq
SELINUX_ROLE_REQUESTED=
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=192.168.28.1 51096 22
SELINUX_USE_CURRENT_RANGE=
SSH_TTY=/dev/pts/0
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/opt
LANG=zh_CN.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
SSH_CONNECTION=192.168.28.1 51096 192.168.28.10 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
DISPLAY=localhost:10.0
OLDPWD=/root
_=/usr/bin/env

[root@yzq opt]# echo $RANDOM 
15805
[root@yzq opt]# echo $RANDOM 
28579
[root@yzq opt]# echo $RANDOM 
15265

echo KaTeX parse error: Expected 'EOF', got '#' at position 10: PATH #̲查看当前搜索路径 PATH="PATH:/root" #将/root目录添加到搜索路径
export PATH=“$PATH:/root” #输出为全局环境变量

环境变量的全局配置文件为/etc/profile,在此文件中定义的变量作用于所有用户。

但环境变量被覆盖时,可进入虚拟机/etc/profile文件加入这行修改
export PATH=“/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin”

或打开另一台虚拟机,使用远程复制/etc/profile到环境变量损坏的主机

3.预定义变量⭐⭐

Bash中内置的一类变量,不能直接修改
$? 上一条命令执行是否成功 0 成功 非零 失败
$# 表示命令或脚本要处理的参数的个数。
$$ 限制当前进程的pid号
$! 返回最后一个后台进程的进程号
$0:表示当前执行的脚本或命令的名称。

∗ 、 *、 @:表示命令或脚本要处理的参数。
$* 表示把所有参数看成以空格分隔的一个字符串整体,代表"$1 $2 $3 $4" (脚本后面的所有内容)

[root@yzq opt]# ls
1.txt  echo.sh  mianji.sh  read.sh  rh  tar.1.txt.gzip  tx  weizhi.sh
[root@yzq opt]# vim test.sh
[root@yzq opt]# chmod +x test.sh 
[root@yzq opt]# ./test.sh echo.sh read.sh  weizhi.sh 
#!/bin/bash
echo -n "薪资"
read offer
echo $offer
#!/bin/bash
read -p "薪资" offer
echo "${offer}k"
#!/bin/bash
echo "位置变量0为$0
      位置变量1为$1
      位置变量2为$2
"
[root@yzq opt]# cat test.sh 
#!/bin/bash
cat $*

$@ 表示把各个参数加上双引号分隔成n份的参数列表,每个参数是独立的个体,代表"$1" “$2” “$3” “$4”。
$$ 返回当前进程的进程号。
$! 返回最后一个后台进程的进程号。

4.位置变量

$n:n为数字,$0代表命令本身,$1-$9代表带一个到第九个参数,十以上的参数需要使用大括号表示,比如${10}
[root@yzq opt]# vim weizhi.sh
[root@yzq opt]# chmod +x weizhi.sh 
[root@yzq opt]# ./weizhi.sh a b
位置变量0为./weizhi.sh
      位置变量1为a
      位置变量2为b

[root@yzq opt]# cat weizhi.sh 
#!/bin/bash
echo "位置变量0为$0
      位置变量1为$1
      位置变量2为$2
"

赋值

**{}**定义整体(分割)

[root@yzq opt]# nihao=yy
[root@yzq opt]# echo $nihao
yy
[root@yzq opt]# echo $nihao1

[root@yzq opt]# echo ${nihao}1
yy1

赋值时使用引号

双引号“”:允许通过$符号引用其他变量值

双引号主要起界定字符串的作用,特别是当要赋值的内容中包含空格时,必须以双引号括起来;其他情况下双引号通常可以省略

[root@yzq opt]# echo $nihao
yy
[root@yzq opt]# echo "$nihao"
yy

单引号‘’:禁止引用其他变量值,$视为普通字符

[root@yzq opt]# echo $nihao
yy
[root@yzq opt]# echo '$nihao'
$nihao
[root@yzq opt]# yy='nihao a'
[root@yzq opt]# echo $yy
nihao a

反撇号``:命令替换,提取命令执行后的输出结果,和$(…)作用相同

允许将执行某个命令的屏幕输出结果赋值给变量。
反撇号括起来的范围内必须是能够执行的命令行,否则将会出错
使用反撇号难以在一行命令中实现嵌套命令替换操作,这时可以改用 “$()”来代替反撇号操作,以解决嵌套的问题

[root@yzq opt]# demo=`cat tx`
[root@yzq opt]# echo $demo 
dd ff gg
[root@yzq opt]# cat=$(cat tx)
[root@yzq opt]# echo $cat 
dd ff gg

[root@yzq opt]# rpm -qc `rpm -qf `which useradd``
rpm:未给出要查询的参数
未安装软件包 useradd 
[root@yzq opt]# which useradd 
/usr/sbin/useradd
[root@yzq opt]# rpm -qc /usr/sbin/useradd
未安装软件包 /usr/sbin/useradd 
[root@yzq opt]# which useradd 
/usr/sbin/useradd
[root@yzq opt]# rpm -qf /usr/sbin/useradd
shadow-utils-4.1.5.1-25.el7.x86_64
[root@yzq opt]# rpm -qc shadow-utils-4.1.5.1-25.el7.x86_64
/etc/default/useradd
/etc/login.defs
[root@yzq opt]# rpm -qc $(rpm -qf $(which useradd))
/etc/default/useradd
/etc/login.defs

交互式定义变量read

可以使用 Bash 的内置命令 read 来给变量赋值。
用来提示用户输入信息,从而实现简单的交互过程。执行时将从标准输入设备(键盘)读入 一行内容,并以空格为分隔符,将读入的各字段依次赋值给指定的变量(多余的内容赋值给 最后一个变量)。若指定的变量只有一个,则将整行内容赋值给此变量。

[root@yzq opt]# read nihao
hello
[root@yzq opt]# echo $nihao
hello

交互式定义变量(read)参数
-p 提示用户的信息
-n 定义字符数
-s 不显示用户输入的内容,常用于输入密码

read -p “提示信息” 变量名
echo $变量名

[root@yzq opt]# read -p "今天周几:" week
今天周几:周四        
[root@yzq opt]# echo $week
周四
[root@yzq opt]# cat read.sh 
#!/bin/bash
read -p "薪资" offer
echo "${offer}k"
[root@yzq opt]# ./read.sh 
薪资20
20k

echo -n “提示信息”
read 变量名
echo $变量名

[root@yzq opt]# cat echo.sh 
#!/bin/bash
echo -n "薪资"
read offer
echo $offer
[root@yzq opt]# ./echo.sh 
薪资21
21

5.全局变量export

默认情况下,新定义的变量只在当前的Shell环境中有效,因此称为局部变量。当进入子程序或新的子Shell环境时,局部变量将无法再使用。

[root@yzq opt]# a=11
[root@yzq opt]# echo $a
11
[root@yzq opt]# su
[root@yzq opt]# echo $a

[root@yzq opt]# exit
exit
[root@yzq opt]# echo $a
11

可以通过内部命令export将指定的变量导出为全局变量,使用户定义的变量在所有的子Shell环境中能够继续使用。
为了使用户定义的变量在所有的子 shell环境中能够继续使用,减少重复设置工作,可以通过内部命令export将指定的变量导出为全局变量。用户可以同时指定多个变量名称作为参数(无须使用"$"符号),变量名之间以空格分隔.

格式1:export 变量名
格式2:export 变量名 = 变量值

[root@yzq opt]# export b=22
[root@yzq opt]# echo $b
22
[root@yzq opt]# su
[root@yzq opt]# echo $b
22

6.整数变量的运算

格式:expr 变量1 运算符 变量2 [运算符 变量3] (整数参数)
运算符:+ 加法、- 减法、* 乘法、/ 除法、% 取余
运算符号: ( ( ) ) 和 (())和 (())[ ] (必须和echo一起用才能输出结果)
运算命令:expr和let
运算工具:bc(系统自带)

[root@yzq opt]# expr 3 - 2
1
[root@yzq opt]# expr 3.0 - 2
expr: 非整数参数,支持常量和变量运算

[ ] 变量的运算可以省略 [ ] 里的 [ ]变量的运算可以省略[ ]里的 []变量的运算可以省略[]里的

[root@yzq opt]# a=5
[root@yzq opt]# b=2
[root@yzq opt]# echo $[a+b]
7
[root@yzq opt]# echo $[$a+$b]
7

let运算
可以改变变量本身的值,但不显示结果,需要echo,其他运算方式可以做运算但不改变变量本身的值

[root@yzq opt]# n=0
[root@yzq opt]# let n=n++
[root@yzq opt]# echo $n
0

使用bc运算,支持小数运算,可用echo结合管道 | 使用
scale定义小数点后几位

[root@yzq opt]# 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'. 
scale=2
14/100
.14
[root@yzq opt]# echo "scale=2;14/100" | bc
.14

bc还可以做逻辑运算,真为1假为0(单=为赋值,不能用,使用双==)

[root@yzq opt]# echo "2>2" | bc
0
[root@yzq opt]# echo "2==2" | bc
1

常用的运算表达式:

i=KaTeX parse error: Undefined control sequence: \* at position 10: (expr 12 \̲*̲ 5) i=((12 * 5))
i=$[12 * 5]
let i=12*5

[root@yzq opt]# i=$(expr 12 \* 5)
[root@yzq opt]# echo $i
60
[root@yzq opt]# i=$(expr 12 * 5)
expr: 语法错误
[root@yzq opt]# i=$(12 * 5)
bash: 12: 未找到命令...
[root@yzq opt]# i=$((12 * 5))
[root@yzq opt]# echo $i
60
[root@yzq opt]# i=$[12 * 5]
[root@yzq opt]# echo $i
60
[root@yzq opt]# let i=12*5
[root@yzq opt]# echo $i
60

i++ 相当于 i= [ [ [i+1]
i-- 相当于 i= [ [ [i-1]
i+=2 相当于 i= [ [ [i+2]

++ i 是先加后赋值;i ++ 是先赋值后加

[root@yzq opt]# i=0
[root@yzq opt]# echo $i
0
[root@yzq opt]# let i=i++
[root@yzq opt]# echo $i
0
[root@yzq opt]# let i=++i
[root@yzq opt]# echo $i
1

7.只读变量

readonly 命令设置只读变量

[root@yzq opt]# yy=1
[root@yzq opt]# echo $yy
1
[root@yzq opt]# readonly yy
[root@yzq opt]# yy=2
bash: yy: 只读变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值