一、bash的特殊字符的意义

1.1、通配符和其他特殊符号

1.1.1 通配符
通配符作用
?匹配一个任意字符
*匹配0个或任意多个任意字符,也就是可以匹配任何内容
[]匹配中括号中任意一个字符。例如:[abc]代表一定匹配一个字符,或者是a,或者是b,或者是c
[-]匹配中括号中任意一个字符,-代表一个范围。例如:[a-z]代表匹配一个小写字母
[^]逻辑非,代表匹配不是中括号内的一个字符,例如:[ ^ 0-9 ]表示匹配一个不是数字的字符
1.1.2 其他特殊符号
符号作用
’ ’单引号(强引用)。单引号中所有的特殊符号,如‘$‘和‘`’(反引号)都没有特殊含义。
" "双引号(弱引用)。在双引号中特殊符号都没有特殊含义,但是"$" 和" "是例外,拥有“调用变量的值”,“引用命令”和“转义符”的特殊含义
``(在table键的上面)反引号。反引号括起来的内容是系统命令,在Bash中会先执行它。和( ) 作 用 一 样 , 不 过 推 荐 使 用 ()作用一样,不过推荐使用()作用一样,不过推荐使用(),因为反引号非常容易看错。
$()用来引用系统命令
#在Shell脚本中,#开头的行代表注释,除此之外脚本的第一行(#!)和超级管理员用户(#)
$用于调用变量的值,如需要调用变量name的值时,需要用$name的方式得到变量的值
\转义符,跟在\之后的特殊符号将失去特殊含义,变为普通字符。如$将输出"$"符号,而不当做是变量引用
取反
$?此变量值在使用的时候,返回的是最后一个命令、函数、或脚本的退出状态码值,如果没有错误则是0,如果为非0,则表示在此之前的最后一次执行有错误。
/在作为运算符的时候,表示除法符号,比如a=4/2
$$进程ID变量,这个变量保存了运行当前脚本的进程ID值。
&如果命令后面跟上一个&符号,这个命令将会在后台运行。
()用于一串命令执行时,()中的命令会在子shell中运行
{}用于一串命令执行时,{}中的命令会在当前shell中执行,也可以用于变量的替换和变形
  • 注意:反引号``在系统中容易被看成单引号,所以使用时,可以用$()代替

定义变量

[root@myx01~]$ a=hello
[root@myx01~]$ echo $a
hello

`` 和 $( )功能相同

[root@myx01~]$ a=$(date)
[root@myx01~]$ echo $a
2023年 09月 27日 星期三 15:45:38 CST

[root@myx01~]$ a=`date`
[root@myx01~]$ echo $a
2023年 09月 27日 星期三 15:45:59 CST
反引号``和$()的区别:

1. 反引号容易和单引号混淆;

2. 反引号在多层嵌套使用时需要使用(\`)处理,而使用$(ls)就没有这样的问题。


转义符“\”,

   -e:开启转义

   -n:表示换行

   -t:水平制表符

   -v:垂直制表符

   -b 表示删除前一个字符

() 和 { }

[root@myx01~]$ b=`hostname`
[root@myx01~]$ echo $b
myx01

# 小括号中可以运子shell,子shell中的a和父shell的a值不冲突
[root@myx01~]$ echo $a
2023年 09月 27日 星期三 15:45:59 CST
[root@myx01~]$ (a=test;echo $a)
test
[root@myx01~]$ echo $a
2023年 09月 27日 星期三 15:45:59 CST

# 花括号的作用会替换原有系统的变量的值,在最后一个变量后需要加 ";" 同时花括号的左右需要加空格
[root@myx01~]$ b=123
[root@myx01~]$ echo $b
123
[root@myx01~]$ { b=abc;echo $b; }
abc
[root@myx01~]$ echo $b
abc

二、Bash的变量

2.1、什么是bash变量

变量是shell 传递数据的一种方法。变量是用来代表每个值的符号名。我们可以把变量当成一个容器,脚本可以在内存中存储数据,然后通过变量。就可以在脚本执行中进行修改和访问存储的数据

2.2、变量的语法

name=values

values的类型一般有如下几种:

1)字符串:name=root
2)引用变量: name="$PATH"
3)命令引用: name=`COMMAND` 或者name=$(COMMAND)

变量引用

echo $NAME

强引用和弱引用

"$name" 弱引用其中的变量名会被替换成变量的值
'$name' 强引用其中的变量名不会被替换成变量的值,而保持其原本的字符串

2.3、 变量的命名规则

1)、 变量名称通常是大写字母,它可以由数字字母(大小写)下划线组成。但是要注意变量名称不能以数字特殊字符开头

[root@myx01~]$ name1=zhangsan
[root@myx01~]$ 1name=zhangsan
-bash: 1name=zhangsan: 未找到命令
[root@myx01~]$ _name2=zhangsan

2)、 等号 = 用于为变量分配值,在使用过程中等号两边不能有空格

[root@myx01~]$ name = zhangsan
-bash: name: 未找到命令
[root@myx01~]$ name= zhangsan
-bash: zhangsan: 未找到命令
[root@myx01~]$ name =zhangsan
-bash: name: 未找到命令

3)、 变量存储的数据类型是整数值和字符串值,但是整数型也会被定义为字符串型

[root@myx01~]$ a=100
[root@myx01~]$ b=200
[root@myx01~]$ c=$a+$b
[root@myx01~]$ echo $c
100+200

4)、 在对变量赋于字符串值时,如果字符串中存在空格,需要使用单引号或双引号把它引起来

[root@myx01~]$ city='wu han'
[root@myx01~]$ city="wu han"
[root@myx01~]$ city=wu han
-bash: han: 未找到命令

5)、 要对变量进行调用,可以在变量名称前加美元符号$

[root@myx01~]$ echo $city
wu han

6)、 如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含“$变量名”或用${变量名}添加的内容

[root@myx01~]$ echo ${city} ni hao!		#方法一
wu han ni hao!

[root@myx01~]$ echo "$city" ni hao!		#方法二
wu han ni hao!

7)、变量命名时要注意“见名知义”,一目了然,能体现出实际的含义

[root@myx01~]$  mem_monitor=$(free -m | grep -i mem)
[root@myx01~]$ echo $mem_monitor
Mem: 1819 188 1452 9 178 1476

8)、变量命名时变量名称最好采用驼峰体,小驼峰studentName,大驼峰StudentName

[root@myx01~]$ Mem_Monitor=$(free -m |grep -i mem)
[root@myx01~]$ echo $Mem_Monitor
Mem: 1819 188 1452 9 178 1476

9)、不要使用系统中保留的关键字:if,for,else,exit,continue

2.4、BASE SHELL的扩展功能

我们最常见的就是扩展变量值和命令替换和算术扩展:

1)、 $name是${name}的简化版本,但是在某些情况下,还必须使用花括号引起的方式来消除歧义并避免意外的结果

2)、 命令的替换就是将命令的调用替换为执行命令后的结果的输出,它的使用方式:我们将命令括在``中 旧形式来调用命令结果,(新形式)是使用$()语法

3)、 在命令替换中,使用新语法$(),它允许进行嵌套命令替换

示例1:变量中的“_”

[root@myx01~]$ name=mengyaunxi
[root@myx01~]$ age=20
[root@myx01~]$ echo $name$age
mengyaunxi20
[root@myx01~]$ echo $name_$age  ##因为“_”可以作为变量名,系统误认为$name_也是一个变量名,会出现错误的结果
20
[root@myx01~]$ echo ${name}_$age  ##必须要花括号来进行消除歧义
mengyaunxi_20
[root@myx01~]$ echo ${name}_${age}
mengyaunxi_20

示例2:将命令的结果赋值给变量

[root@myx01/tmp]$ swap=`free -h | grep -i swap`
[root@myx01/tmp]$ echo $swap
Swap: 2.0G 0B 2.0G
##添加压缩文件
[root@myx01~]$ mkdir {1..5}.txt
[root@myx01~]$ var1=$(tar cvf /tmp/a.tar $(find /root -name "*.txt"))
tar: Removing leading `/' from member names
[root@myx01~]$ echo $var1
/root/1.txt/ /root/2.txt/ /root/3.txt/ /root/4.txt/ /root/5.txt/

示例3:将SWAP内存内存传递给变量

[root@myx01~]$ swap=`free -h | grep -i swap`
[root@myx01~]$ echo $swap
Swap: 2.0G 0B 2.0G

[root@myx01~]$ swap=$(free -h|grep -i swap)
[root@myx01~]$ echo $swap
Swap: 2.0G 0B 2.0G

示例4:变量切割

[root@myx01~]$ num=123456
[root@myx01~]$ echo ${num:2:3}		# 2:第三位(1是第零位,2是第一位以此类推) 3:往后截取的位数
345
[root@myx01~]$ echo ${num:2}
3456
[root@myx01~]$ echo ${num:2:-1}		# -1 取最后一个值
345

4)、进行算术扩展时使用$[]进行,同时它也允许算术替换

[root@myx01~]$ num1=20
[root@myx01~]$ num2=5
[root@myx01~]$ echo $[ $num1 / $num2 ]
4
[root@myx01~]$ echo $[ $num1 % $num2 ]
0
[root@myx01~]$ echo $[ $num1 - $num2 ]
15
[root@myx01~]$ echo $[ $num1 + $num2 ]
25
[root@myx01~]$ echo $[ $num1 * $num2 ]
100
[root@myx01~]$ echo $[ $num1 ** $num2 ]
3200000

2.5、变量类型

1)、用户自定义变量:用户自定义的变量,仅本地有效,其他进程及当前进程的子进程无效。

2)、环境变量:这种变量中主要保存的是和系统操作环境相关的数据。

3)、位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。

4)、预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
2.5.1 用户自定义变量

由字母或下划线打头,不允许数字开头,后面由字母、数字或下划线组成,并且大小写字母意义不同。变量名长度没有限制。

使用变量值时,要在变量名前加上前缀“$”。

2.5.1.1 定义自定义变量

示例:创建一个自定义变量

[root@myx01~]$ name=myx

示例:在对变量赋值时,可以引用系统变量

[root@myx01~]$ name="$PATH"
[root@myx01~]$ echo $name
/usr/local/node/bin/:/apps/tree/bin:/apps/httpd/bin:/apps/cmatrix/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
2.5.1.2 查询变量 setenv

注意:env查看不到自定义的变量(只能查看当前用户环境变量),set可以查看当前用户的所有的变量

[root@myx01~]$ set | grep myx
HOSTNAME=myx01
name=myx

[root@myx01~]$ env | grep myx
HOSTNAME=myx01
语法:set  [变量名]
-u:当查看一个不存在的变量的时候直接反馈  “变量不存在”

-x: 如果设置此选项,在命令执行之前,会先把命令输出一次

-e: 如果语法执行有问题,则停止执行

示例:

[root@myx01~]$ echo $abc			##未设置-u参数之前

[root@myx01~]$ a="bcd"
[root@myx01~]$ echo $a
bcd

[root@myx01~]$ set -u				##设置-u参数之后
[root@myx01~]$ echo $bcd
-bash: aaa: unbound variable
[root@myx01~]$ echo $a
bcd
2.5.1.3 删除变量
语法:unset  [变量名]
[root@myx01~]$ name=MYX
[root@myx01~]$ set | grep MYX
name=MYX

[root@myx01~]$ unset name
[root@myx01~]$ set | grep MYX

也可以一次性删除多个变量

[root@myx01~]$ unset name title      ##同时删除name,title变量
[root@myx01~]$ echo $name $title

注意:变量是临时存放在内存中的,当终端退出后,变量会被删除,定义好的变量无法跨终端查看

2.5.2 环境变量

环境变量:用户自定义环境变量和系统环境变量

用户自定义环境变量和用户定义变量的区别:

1)“用户自定义环境变量” 可以在当前终端和子shell中生效 ,切换终端会失效
   临时:export NAME=VALUES	
   永久:/etc/profile,/etc/bashrc/.bashrc
   
2)“用户自定义变量” 只能在当前shell中生效
   语法:NAME=VALUES

image20230928145500478.png 查看进程

[root@myx01~]$ pstree -p

结论:用户自定义变量只能在当前自己的bash环境中运行,无法跨bash执行。如果想让子shell能执行父shell的变量,必须要将变量定义为自定义环境变量,反过来,父shell无法继承子shell的变量的值。

2.5.2.2 系统环境变量
bash中常见的内建环境变量:
  PATH
  SHELL
  USER
  UID
  HOME
  PWD
  SHLVL    ##shell锲套的层数
  LANG
  MAIL
  HOSTNAME
  HISTSIZE
  _  	  ##表示上一个命令的最后一个参数
##查看系统环境变量
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
2.5.2.3 PS1环境变量
 命令提示符设置

在Linux中,PS1是一个全局变量,查看PS1的格式如

[root@localhost ~]# echo $PS1
[\u@\h \W]\$

1**)设置PS1变量的格式**

 PS1='[\u@\h \w]\$ ' 

----注意$后面有一个空格!如果没有空格的话,将会报错!

   \d :代表日期,格式为weekday month date,例如:"Mon Aug 1" 

  \H :完整的主机名称。例如:我的机器名称为:akesu.linux,则这个名称就是akesu.linux 

  \h :仅取主机的第一个名字,如上例,则为akesu,.linux则被省略 

  \t :显示时间为24小时格式,如:HH:MM:SS 

  \T :显示时间为12小时格式 

  \A :显示时间为24小时格式:HH:MM 

  \u :当前用户的账号名称 

  \v :BASH的版本信息 

  \w :完整的工作目录名称。家目录会以 ~代替 

  \W :利用basename取得工作目录名称,所以只会列出最后一个目录 

  \# :下达的第几个命令 

  \$ :提示字符,如果是root时,提示符为:# ,普通用户则为:$
[root@localhost:w 20:18:09]$ PS1='[\u@\h:\w \t]$ '

以上设置均时临时生效,需要永久生效需要写入/etc/bashrc文件中。

2.5.2.4 lang变量

用于系统使用的语言

[root@localhost:/etc 20:22:21]$ echo $LANG
en_US.UTF-8

[root@localhost:/etc 20:24:17]$ locale -a  --查看系统中支持的语言
[root@localhost:/etc 20:24:17]$ locale   --查看当前安装的语言
[root@localhost:/etc 20:23:04]$ LANG=zh_CN_UTF-8   --设置当前的语序
[root@localhost:/etc 20:23:29]$ echo $LANG
zh_CN_UTF-8

可以通过在/etc/locale.conf这个文件查看当前系统的默认语系,可以进行修改。

vi /etc/locale.conf
LANG="zh_CN.UTF-8"
# LANG="en_US.UTF-8"

2.6 位置参数变量

Shell解释执行用户的命令时,将命令行的第一个字作为命令名,而其它字作为参数。由出现在命令行上的位置确定的参数称为位置参数。

使用$N 来表示

$n:n 为数字,$0 代表命令本身,$1-$9 代表第一到第九个参数,十以上的参数需要用大括号包含,如 ${10}。

$ *:这个变量代表命令行中所有的参数,$* 把所有的参数看成一个整体。
	$* 11 22 33 44          # $* 作为一个整体输出

$@:这个变量也代表命令行中所有的参数,不过 $@ 把每个参数区分对待。
	$@ 	11		# $@将每个参数单独输出
		22
		33
		44

$#:这个变量代表命令行中所有参数的个数。
	$# 	4
set --      ##清除所有的位置参数

案例:位置参数应用于文件管理

#!/bin/bash

WARNNING_COLOR="echo -e \e[1;31m"     ##定义告警颜色
END="\e[0m"                            
DIR=/tmp/`date +%F_%H-%M-%S`         ##定义临时目录位置
mkdir $DIR                           ##创建临时目录
mv $1 $DIR                           ##移动文件到临时目录

${WARNNING_COLOR}move $1 to $DIR $END       ##打印移动文件内容信息
[root@localhost shells]# alias rm=/data/shells/rm.sh    ##定义别名
测试:
[root@localhost ~]# touch a 
[root@localhost ~]# rm a
move a to /tmp/2022-08-12_21-15-39 

注意:如果想同时删除多个文件,将位置参数 $1 修改成 $*,即可表示所有的位置参数。

面试扩展题:鸡兔同笼问题:笼子里有30只头,68只脚,兔多少?鸡多少?

#!/bin/bash
#Description:     The test script
#QQ:             2041598918
#Author:          mengyuanxi
#email:          2041598918@qq.com 
#FileName:        jitutonglong.sh
#Date:            2023-10-07
#=======================================================
read -p "头数:" TOU
read -p "脚数:" JIAO
# 头数和脚数的总和
total_heads=TOU
total_legs=JIAO

# 鸡和兔的脚数
chicken_legs=2
rabbit_legs=4

# 鸡和兔的数量设为未知数
chicken_count=0
rabbit_count=0

# 通过方程求解计算兔的数量
rabbit_count=$(( (total_legs - 2 * total_heads) / 2 ))

# 计算鸡的数量
chicken_count=$(( total_heads - rabbit_count ))

# 输出结果
echo "鸡的数量: $chicken_count"
echo "兔的数量: $rabbit_count"

2.7 特殊变量

符号作用
$?显示最后命令的退出状态;0表示没有错误,其他任何值表明有错误 :1-255exit 100 # 自定义状态码
$!后台运行的最后一个进程的进程号pidecho $!
$$当前进程的进程号PIDecho $$

2.8 只读变量

只读变量的定义方法:

readonly        [name]
declare   -r    [name]

示例:

[root@localhost ~]# readonly a=100
[root@localhost ~]# a=20
-bash: a: 只读变量

[root@localhost ~]# declare -r b=200
[root@localhost ~]# b=300
-bash: b: 只读变量

2.9 read接收键盘输入

语法:
[root@localhost ~]# read [选项]  [变量名]
选项:
  -p   "提示信息"  在等待read输入时,输出提示信息
  -t   秒数        read命令会一直等待用户的输入,使用此选项可以指定等待的时间
  -n   字符数      read 命令只接受指定的字符数
  -s   隐藏字符

扩展面试题:为什么使用echo获取不到值?

[root@localhost ~]# cat a.txt 
1 2
[root@localhost ~]# read x y <a.txt ; echo x=$x y=$y 
x=1 y=2
[root@localhost ~]# echo 1 2 |read x y ;echo $x $y   ##没有结果


[root@localhost ~]# echo 1 2 |(read x y ;echo $x $y)  ##在子shell中,每一个命令都被管道当成一个独立的进程进行来执行,
1 2

三、全局环境变量

环境变量的配置文件主要有5类:

1、全局配置文件:
    /etc/profile:为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行,并从指定目录中(通常为/etc/profile.d)的配置文件中搜集shell的设置
    /etc/bashrc:为每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被执行
    
2、用户配置文件:
    ~/.bash_profile:用户使用该文件设定专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件
    ~/.bashrc:该文件包含专用于用户的bash shell的bash信息,当登录时以及每次打开新的shell时,该文件被读取
    ~/.bash_logout:当每次退出系统(退出bash shell)时,执行该文件

3.1 环境变量详细加载过程

image-20220103135352275

常用的环境变量

变量名称作用
HOME用户的主目录(即家目录)
SHELL用户在使用的Shell解释器名称
HISTSIZE输出的历史命令记录条数
HISTFILESIZE保存的历史命令记录条数
MAIL邮件保存路径
LANG系统语言、语系名称
RANDOM生成一个随机数字
PS1Bash解释器的提示符
PATH定义解释器搜索用户执行命令的路径
EDITOR用户默认的文本编辑器
3.1.2 环境变量

1、 用户环境变量

(1).bash_profile :定义了用户的个人化路径与环境变量的文件名称。

(2).bashrc :该文件包含专用于你的shell的bash信息,当登录时以及每次打开新的shell时,该该文件被读取。

(3).bash_history :记录命令历史用的。

(4).bash_logout :当退出shell时,会执行该文件。可以把一些清理的工作放到这个文件中。

四、用户登录提示信息设置

4.1、 shell登陆信息 /etc/issue

常见的几个选项

\d 显示当前日期;  date
\l 显示虚拟控制台号;
\m 显示机器类型,即 CPU 架构,如 i386 或 x86_64 等(相当于 uname -m);
\n 显示主机的网络名(相当于 uname -n);
\o 显示域名;
\r 显示 Kernel 内核版本号(相当于 uname -r);
\t 显示当前时间;
\s 显示当前操作系统名称;
\u 显示当前登录用户的编号,\U 显示当前登录用户的编号和用户;
\v 显示当前操作系统的版本日期;

4.2、 ssh 输入用户名后欢迎信息设置/etc/ssh/sshd_config

当前输入用户后,并没有显示任何欢迎信息,而是直接弹出输入密码提示。

vim  /etc/ssh/sshd_config

image.png

touch /etc/ssh/Banner
echo "welcome to MYX" >/etc/ssh/Banner

systemctl restart sshd

4.3、 ssh 输入密码后欢迎信息设置/etc/motd

1)可以修改 /etc/motd 文件,定义 ssh 成功登录后的欢迎信息。