shell编程规范与变量

一、shell相关概念

交互式与非交互式操作
交互式操作:程序运行后,需要用户输入指令引导程序一步一步地处理。(类似一问一答)。
非交互式操作:程序运行后,无需用户输入指令引导。(类似一问自答)。

shell脚本应用场景
重复性操作
交互性任务
批量事务处理
服务运行状态监控
定时任务执行

脚本的作用:根据编写内容处理交互性任务,方便快捷的解决大量重复的操作。

计算机架构:
底层硬件 -> 操作系统内核 -> 核外程序 -> 计算机用户

在底层硬件之上安装操作系统内核,在内核之上安装核外程序来使用(shell是核外程序),计算机用户通过核外程序来输入指令,shell负责解释用户指令给系统内核,系统内核调用硬件来完成任务。

查看系统都支持哪些shell
cat /etc/shells
[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash

查看shell的具体属性,发现sh是bash的软连接,说明sh=bash,两者无区别。
[root@localhost ~]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 12月18日 22:48 /bin/sh -> bash


脚本两种执行方式的区别
执行方式一:在当前shell(终端)执行脚本
./aaa.sh # 需要执行(x)权限
sh aaa.sh
bash aaa.sh

执行方式二:新开一个子shell(终端)运行脚本,执行完退出子shell(终端)。
source aaa.sh
. aaa.sh

标准输入  键盘    1<
标准输出  显示器  0>
标准错误  显示器  2>

重定向
>:正确输出,覆盖。
>>:正确输出,追加。
<:输入,覆盖。
<<:输入,追加。
2>:错误输出,覆盖。
2>>:错误输出,追加。
&>:混合输出,正确+错误。

管道符
|:左边命令输出的结果,作为右边命令的输入。
grep:过滤出满足条件的行。
 

[root@localhost ~]# tar zcvf aaa.tar.gz /boot
tar: 从成员名中删除开头的“/”	 # 写绝对路径时,会把根(/)路径删除,避免解压直接解压到原位置。
[root@localhost ~]# tar zxvf aaa.tar.gz
[root@localhost ~]# ls
aaa.tar.gz  anaconda-ks.cfg  boot  pass.txt   # 解压后发现boot目录在当前目录下。

grep awk sed 及正则表达式
grep(global regular expression,全局正则表达式):用于过滤满足条件的行。
例如:
grep "root" /etc/shadow 过滤出包含root的行
grep -v "root" /etc/shadow 过滤出不包含root的行 -v:反向查找

awk:文本分析工具。
例如:
[root@localhost ~]# df | grep "/$" | awk '{print $5}' | awk -F % '{print $1}'
2		# /空间使用情况

sed:利用脚本来处理文本文件。

变量:在内存空间中存储的可变化的量,在内存空间中存储的值都会有一个内粗地址,用于标明身份。用户在使用变量值时,如果每次都要查看变量的内存地址,也太不方便了,此时通过输入变量名即可输出在内存空间中对应的内存地址,也就是屏幕上输出的变量值。

 
变量命名规范
1、不能以数字开头。
2、不能包含特殊符号(如@ $等)。
3、不能是纯数字组合。

设置变量:
变量名=变量值


双引号("):变量值用双引号括起来,代表一个整体,特殊符号具有特殊含义。
例如:aaa=111  name="$aaa",此时echo $name 会输出$aaa的值,即111. 因为name="$aaa",$aaa被双引号括起来,特殊符号$具有特殊含义,表明使用$aaa,所以会输出111.

单引号('):变量值用单引号括起来,代表一个整体,特殊符号没有含义
例如;aaa=222 name='$aaa',此时echo $name 会输出$aaa。因为name='$aaa',$aaa被单引号括起来,特殊符号$不具有特殊含义,$此时只是个普通字符,输出结果自然为$aaa.

反引号(`):变量值是linux命令时需要使用反引号括起来,代表一个整体。或者使用$()将linux命令括起来,也是代表一个整体。
例如:rpm -qf `which useradd` 输出此命令后会显示useradd的rpm包是谁,用反引号括起来linux命令即可使用,如果去掉反引号会报错。
 

$() 和 `` 的区别:$()支持多层嵌套,反引号只支持一层嵌套,如果语句要使用嵌套格式,选择$()。
例如:多层嵌套使用$()
[root@localhost ~]# rpm -qf $(which useradd)
shadow-4.14.3-5.oe2403sp1.x86_64
[root@localhost ~]# rpm -qc shadow-4.14.3-5.oe2403sp1.x86_64
/etc/default/useradd
/etc/login.defs

[root@localhost ~]# rpm -qc $(rpm -qf $(which useradd))  # 嵌套使用命令
/etc/default/useradd
/etc/login.defs

read:与用户交互,接受用户输入的内容赋值给变量。
语法: read -p "提示信息" 变量名

变量相关:
调用变量时:${变量名}
{}:变量名要用{}括起来,代表一个整体。
 
全局变量:在任何终端都可用。
局部变量:只在当前shell终端可用。

export 变量名 将已有的局部变量声明为全局变量。

export 变量名=变量值  设置变量时就将该变量声明为全局变量。

环境变量是一个总称,代表系统变量和用户变量。

系统变量:系统级别的变量,更改此变量会影响所有系统用户。系统变量中通常存储了系统命令的搜索路径。

用户变量:用户级别的变量,更改此变量只会影响该用户。用户变量中通常存储了该用户自定义的搜索路径。

数值运算相关:
expr 
+:加
-:减
*:乘
/:除
%:取余
语法: expr 变量 运算符 变量  注意空格

set:显示系统中所有的环境变量,包括全局变量和局部变量。
env:显示当前的全局变量。


优化系统路径(path)的方式:
cp 脚本名 /usr/local/sbin   1、复制所需脚本到/bin或/sbin下。
软链接 脚本名  /usr/local/sbin  2、软链接方式
vim /etc/profile PATH=$PATH:/路径  source /etc/profile  3、写入系统变量


位置参数 $0 $1 的区别
$0代表当前执行的进程/程序名
$1代表第一个位置参数


$#:命令行中位置变量的个数。 
$*:所有位置变量的内容。
$?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错。
$0:当前执行的进程/程序名。
 

二、脚本示例

一、脚本两种执行方式的区别
[root@localhost ~]# cat aaa.sh 
#!/bin/bash		# 脚本第一行为说明信息,告诉系统这个脚本需要什么解释器来执行。
cd /boot
pwd
ls -l

[root@localhost ~]# . aaa.sh 
/boot
总计 163988
-rw-r--r--. 1 root root   238365 12月27日 12:19 config-6.6.0-72.0.0.76.oe2403sp1.x86_64
drwxr-xr-x. 2 root root     4096 12月24日 10:47 dracut
drwxr-xr-x. 3 root root     4096 2025年 3月 1日 efi
drwx------. 6 root root     4096 2025年 3月 1日 grub2
-rw-------. 1 root root 65022738 2025年 3月 1日 initramfs-0-rescue-8c899201cf284bc98f5ef36f063fcc14.img
-rw-------. 1 root root 30258146 2025年 3月 1日 initramfs-6.6.0-72.0.0.76.oe2403sp1.x86_64.img
-rw-------. 1 root root 36850688 2025年 3月 1日 initramfs-6.6.0-72.0.0.76.oe2403sp1.x86_64kdump.img
drwxr-xr-x. 3 root root     4096 2025年 3月 1日 loader
drwx------. 2 root root    16384 2025年 3月 1日 lost+found
-rw-r--r--. 1 root root   312306 12月27日 12:19 symvers-6.6.0-72.0.0.76.oe2403sp1.x86_64.gz
-rw-r--r--. 1 root root  6949973 12月27日 12:19 System.map-6.6.0-72.0.0.76.oe2403sp1.x86_64
-rw-r--r--. 1 root root 14119392 2025年 3月 1日 vmlinuz-0-rescue-8c899201cf284bc98f5ef36f063fcc14
-rw-r--r--. 1 root root 14119392 12月27日 12:19 vmlinuz-6.6.0-72.0.0.76.oe2403sp1.x86_64
[root@localhost boot]# 

执行完脚本,工作路径换到了boot。

[root@localhost ~]# ./aaa.sh 
/boot
总计 163988
-rw-r--r--. 1 root root   238365 12月27日 12:19 config-6.6.0-72.0.0.76.oe2403sp1.x86_64
drwxr-xr-x. 2 root root     4096 12月24日 10:47 dracut
drwxr-xr-x. 3 root root     4096 2025年 3月 1日 efi
drwx------. 6 root root     4096 2025年 3月 1日 grub2
-rw-------. 1 root root 65022738 2025年 3月 1日 initramfs-0-rescue-8c899201cf284bc98f5ef36f063fcc14.img
-rw-------. 1 root root 30258146 2025年 3月 1日 initramfs-6.6.0-72.0.0.76.oe2403sp1.x86_64.img
-rw-------. 1 root root 36850688 2025年 3月 1日 initramfs-6.6.0-72.0.0.76.oe2403sp1.x86_64kdump.img
drwxr-xr-x. 3 root root     4096 2025年 3月 1日 loader
drwx------. 2 root root    16384 2025年 3月 1日 lost+found
-rw-r--r--. 1 root root   312306 12月27日 12:19 symvers-6.6.0-72.0.0.76.oe2403sp1.x86_64.gz
-rw-r--r--. 1 root root  6949973 12月27日 12:19 System.map-6.6.0-72.0.0.76.oe2403sp1.x86_64
-rw-r--r--. 1 root root 14119392 2025年 3月 1日 vmlinuz-0-rescue-8c899201cf284bc98f5ef36f063fcc14
-rw-r--r--. 1 root root 14119392 12月27日 12:19 vmlinuz-6.6.0-72.0.0.76.oe2403sp1.x86_64
[root@localhost ~]# 
执行完脚本,工作目录未发生改变。

二、重定向
[root@localhost ~]# setenforce 0	# 关闭后才可以使用stdin来实现脚本创建用户和创建用户密码。
[root@localhost ~]# vim bbb.sh
#!/bin/bash
useradd ooos
passwd --stdin ooos < pass.txt		# 重定向输入

[root@localhost ~]# cat pass.txt 
123

[root@localhost ~]# chmod +x bbb.sh
[root@localhost ~]# ./bbb.sh 
更改用户 ooos 的密码 。
passwd:所有的身份验证令牌已经成功更新。


[root@localhost ~]# ls -l > 1.txt
[root@localhost ~]# ls -l > 1.txt
[root@localhost ~]# ls -l > 1.txt
[root@localhost ~]# ls -l > 1.txt	# 将标准输出重定向覆盖输出至1.txt
[root@localhost ~]# ls
1.txt  aaa.sh  anaconda-ks.cfg  bbb.sh  pass.txt
[root@localhost ~]# cat 1.txt 
总计 16
-rw-r--r--. 1 root root    0  3月 1日 10:45 1.txt
-rwxr-xr-x. 1 root root   31  3月 1日 10:30 aaa.sh
-rw-------. 1 root root 1271 2025年 3月 1日 anaconda-ks.cfg
-rwxr-xr-x. 1 root root   56  3月 1日 10:37 bbb.sh
-rw-r--r--. 1 root root    4  3月 1日 10:37 pass.txt

[root@localhost ~]# ls -l >> 1.txt
[root@localhost ~]# ls -l >> 1.txt
[root@localhost ~]# ls -l >> 1.txt	# 将标准输出重定向追加输出至1.txt
[root@localhost ~]# cat 1.txt 
总计 16
-rw-r--r--. 1 root root    0  3月 1日 10:46 1.txt
-rwxr-xr-x. 1 root root   31  3月 1日 10:30 aaa.sh
-rw-------. 1 root root 1271 2025年 3月 1日 anaconda-ks.cfg
-rwxr-xr-x. 1 root root   56  3月 1日 10:37 bbb.sh
-rw-r--r--. 1 root root    4  3月 1日 10:37 pass.txt
总计 20
-rw-r--r--. 1 root root  286  3月 1日 10:46 1.txt
-rwxr-xr-x. 1 root root   31  3月 1日 10:30 aaa.sh
-rw-------. 1 root root 1271 2025年 3月 1日 anaconda-ks.cfg
-rwxr-xr-x. 1 root root   56  3月 1日 10:37 bbb.sh
-rw-r--r--. 1 root root    4  3月 1日 10:37 pass.txt
总计 20
-rw-r--r--. 1 root root  572  3月 1日 10:47 1.txt
-rwxr-xr-x. 1 root root   31  3月 1日 10:30 aaa.sh
-rw-------. 1 root root 1271 2025年 3月 1日 anaconda-ks.cfg
-rwxr-xr-x. 1 root root   56  3月 1日 10:37 bbb.sh
-rw-r--r--. 1 root root    4  3月 1日 10:37 pass.txt
总计 20
-rw-r--r--. 1 root root  858  3月 1日 10:47 1.txt
-rwxr-xr-x. 1 root root   31  3月 1日 10:30 aaa.sh
-rw-------. 1 root root 1271 2025年 3月 1日 anaconda-ks.cfg
-rwxr-xr-x. 1 root root   56  3月 1日 10:37 bbb.sh
-rw-r--r--. 1 root root    4  3月 1日 10:37 pass.txt


[root@localhost ~]# fsadfadsfa  2> 2.txt 
[root@localhost ~]# fsadfadsfa  2> 2.txt
[root@localhost ~]# fsadfadsfa  2> 2.txt
[root@localhost ~]# fsadfadsfa  2> 2.txt
[root@localhost ~]# fsadfadsfa  2> 2.txt	# 将错误输出重定向覆盖输出到2.txt
[root@localhost ~]# cat 2.txt 
-bash: fsadfadsfa: 未找到命令

[root@localhost ~]# fsadfadsfa  2>> 2.txt
[root@localhost ~]# fsadfadsfa  2>> 2.txt
[root@localhost ~]# fsadfadsfa  2>> 2.txt
[root@localhost ~]# fsadfadsfa  2>> 2.txt	# 将错误输出重定向追加输出到2.txt
[root@localhost ~]# cat 2.txt 
-bash: fsadfadsfa: 未找到命令
-bash: fsadfadsfa: 未找到命令
-bash: fsadfadsfa: 未找到命令
-bash: fsadfadsfa: 未找到命令
-bash: fsadfadsfa: 未找到命令


[root@localhost ~]# ls -a /root  sdfdsf &> 4.txt # 混合(正确+错误)输出到4.txt
[root@localhost ~]# cat 4.txt 
ls: 无法访问 'sdfdsf': No such file or directory
/root:
.
..
1.txt
2.txt
3.txt
4.txt
aaa.sh
anaconda-ks.cfg
.bash_logout
.bash_profile
.bashrc
bbb.sh
.cshrc
pass.txt
.ssh
.tcshrc
.viminfo



[root@localhost ~]# read -p ":"  aaa	# read输出提示符并等待用户赋值给变量
:123
[root@localhost ~]# echo $aaa
123

三、expr运算表达式
[root@localhost ~]# x=20
[root@localhost ~]# y=6

加法:
[root@localhost ~]# expr $x + $y 
26

减法:
[root@localhost ~]# expr $x - $y
14

乘法:
[root@localhost ~]# expr $x * $y
expr: 语法错误:未预期的参数 "1.txt"


[root@localhost ~]# expr $x \* $y	# \转义字符,取消*的特殊含义,使其作为乘。
120	


取余:
[root@localhost ~]# expr $x % $y
2

你可能感兴趣的:(linux)