一、前言
“得道者多助,失道者寡助”
gogogo~!
二、shell基础(2)
BASH的变量与运算符
变量的定义:
- 变量名可以由字符、数字和下划线组成
- 不能以数字开头-->比如2HAHA这个不能识别
- 变量是用=号赋值的
- 变量两边都不能有空格:因为系统会当成了命令来执行
- 变量默认的是字符串类型的,比如定义A=100,这个代表就是字符串,如果需要运行的话,需要定义变量类型了
#定义一个变量
[root@Master ~]# AA=100
[root@Master ~]# echo $AA
100
#如果以数字开头就会直接报错
[root@Master ~]# 2AA=101
-bash: 2AA=101: command not found
#变量的叠加
[root@Master ~]# BB=123
[root@Master ~]# echo $BB
123
[root@Master ~]# BB="$BB"456
[root@Master ~]# echo $BB
123456
[root@Master ~]# BB=${BB}789
[root@Master ~]# echo $BB
123456789
#把命令结果赋予给变量
需要使用反引号或者$()
[root@Master ~]# AA=`date +%F`
[root@Master ~]# echo $AA
2021-01-03
[root@Master ~]# AA=$(date)
[root@Master ~]# echo $AA用户自定义变量
#自己定义
注意:如果变量值有空格,需要双引号引起来
调用变量的值需要跟上$
当前shell生效
[root@Master ~]# NAME="Liang GaRy"
[root@Master ~]# echo $NAME
Liang GaRy环境变量
- 保存系统环境相关的变量
- 环境变量会整个Linux系统生效
- 环境变量建议大写的-->区别于Linux的命令
- SHELL:当前的用户shell
- LANG:当前系统的字符集
- ........
位置变量:
预定义变量-->这个是固定的;
问题:如果变量不存在,或者变量值为空,看如何鉴别?
#定义一个变量值为空
[root@Master ~]# echo $kong
[root@Master ~]# kong=""
[root@Master ~]# echo $kong
#以上两种情况无法区分-->
使用的是set -u命令==》
[root@Master ~]# set -u
[root@Master ~]# echo $kang
-bash: kang: unbound variable
[root@Master ~]# echo $kong
#如果变量存在-->则会有显示
#如果变量不存在-->则会有报错set命令和unset命令
作用:查看变量
语法:
- set -u:变量不存在会有提示,变量存在-->会调用变量值
- 主要用于区分某些特殊变量值有问题,比如空格的问题
[root@Master ~]# set -u
[root@Master ~]# echo $kang
-bash: kang: unbound variable
[root@Master ~]# echo $kong
[root@Master ~]#
#删除变量
[root@Master ~]# SHAN=123456
[root@Master ~]# set | grep SHAN
SHAN=123456
[root@Master ~]# unset SHAN
[root@Master ~]# echo $SHAN
-bash: SHAN: unbound variable
[root@Master ~]# set | grep SHAN
_=SHAN
问题:如何声明环境变量?
#先定义变量
[root@Master ~]# SHAN=18
#声明环境变量
[root@Master ~]# export SHAN
[root@Master ~]# env | grep SHAN
SHAN=18
[root@Master ~]# export SHAN="LALA"
[root@Master ~]# env | grep SHAN
SHAN=LALAenv命令
- 作用:查看系统的环境变量
- 和set命令差不多-->都能查看变量
[root@Master ~]# export SHAN="LALA"
[root@Master ~]# env | grep SHAN
SHAN=LALAPATH环境变量
作用:系统查找命令的路径
默认是用:冒号相隔开
[root@Master ~]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
#自定义的脚本成为系统命令?如何做到?
[root@Master ~]# vim /root/haha.sh
#!/bin/bash
echo "Linux is good"
#把这个脚本放入PATH路径下
[root@Master ~]# PATH=$PATH:/root/haha.sh
[root@Master ~]# chmod a+x haha.sh
惊奇得发现在命令行直接输入
haha+tab能够补全脚本的命令
[root@Master ~]# haha.sh
Linux is goodPS1环境变量
- 作用:定义的是命令行的提示符
- 可以根据需求来修改
- 永久修改-->写入配置文件/etc/bashrc
- 找到PS1的变量
选项:
- \d:显示日期-->默认为“星期、月、日”
- \H:完整的主机名
- \h:显示简写的主机名-->某些字符不显示
- \t:显示24小时时间-->格式为“HH:MM:SS”
- \T:显示12小时时间-->格式为“HH:MM:SS”
- \A:显示24小时时间-->格式为“HH:MM”
- \@:显示时间格式-->格式为“HH:MM am/pm”
- \u:相识当前用户名
- \v:bash版本信息
- \w:显示目的全路径
- \W:显示最后一级目录的名字
- \$:提示符
#查看默认的提示信息
[root@Master ~]# echo $PS1
[\u@\h \W]\$
[]:中括号
\u:显示用户名
\h:显示主机名
\w:显示最后一个目录名称
\$:命令行提示符
#可以自己设定
[root@Master ~]# grep "PS1" /etc/bashrc
if [ "$PS1" ]; then
[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
# if [ "$PS1" ]; then
# PS1="[\u@\h:\l \W]\\$ "
if [ "$PS1" ]; then
#按照格式自己定义
[root@Master ~]# PS1="[\u@\H \w]\$"
[root@Master /etc]$PS1='[\u@\H \w]\$'
#注意双引号和单引号是有区别的
\$:这里代表的是:如果超级用户的是#,如果是普通用户的是$-->它有这两个含义位置参数
1)$n:n为数字
- $0:代表命令本身
- $1-9:代表命令行输入的第1-9个参数-->每个参数用空格隔开
- 如果大于10的需要${},来引用
- 因为shell理解定义a=10,它会理解为字符串,如果需要数值运算,需要使用$(( ))
2)$*:代表命令行中所有的藏书,把1 2 3 4 -->统一看成一个整体,
3)$@:这个代表命令行中所有的参数,1 2 3 4 -->每个数字是独立的,不看做一个整体
4)$#:代表命令行中所有的参数的个数,1 2 3 4 -->这个才是4个参数
#简单的加法运算脚本
[root@Master sh]# vim jiafa.sh
#!/bin/bash
#2021年1月29日14:45:51
#used:加法
a=$1 #定义a-->第一个参数 但是定义的是
b=$2 #定义b-->shell输入的第二个参数
sum=$(( $a + $b )) #$(()) ---->这个代表是数值运算,
echo $sum #输出sum的值
echo $0 #输出命令本身--->这个是$0的作用
#执行脚本
[root@Master sh]# bash jiafa.sh 12 45 #这里输入了12 45 两个参数
57
jiafa.sh #这里就是$0,输出命令本身
#$*和$@的区别:
$*:代表的就所有参数看成一个整体
$@:代表每个参数是独立的歌曲
$#:代表的参数的个数
写个脚本看啊看
[root@Master sh]# vim quebie.sh
#!/bin/bash
#used $* $@ #
echo "\$* is $*"
echo "\$@ is $@"
echo "\$# is $#"
执行脚本
[root@Master sh]# bash quebie.sh 1 2 3 4 8 5
$* is 1 2 3 4 8 5 #输出123485
$@ is 1 2 3 4 8 5 #这个也是输出123482
$# is 6 #这个就是6个参数
那么如何区别$*和$@?
[root@Master sh]# vim quebie2.sh
#!/bin/bash
#used $* $@ quebie
for i in "$*" #for循环-->把$*的值赋予i --->然后输出i
do
echo $i
done
echo -----------------
for y in "$@" #for循环-->把$@的值赋予y-->然后输出y
do
echo $y
done
执行脚本查看一下
[root@Master sh]# bash quebie2.sh 11 22
11 22 #这里就很明显值显示一行,$*把11 22当做一个整体
-----------------
11 #这里就是把11 22 分别当做一个数,然后输出
22其他的系统变量
$?:判断最后一次执行命令是否执行正确-->0为正确-->非0就是错误
$$:能够查看系统的当前进程ID号
$!:查看后台进行的最后一个的ID号
#$?讲解
[root@Master sh]# lsjd #错误命令-->显示非0值
-bash: lsjd: command not found
[root@Master sh]# echo $?
127
[root@Master sh]# echo $? #命令正确-->显示0
0
多数是用来判断
#$$讲解
[root@Master sh]# ll /etc/fstab
-rw-r--r--. 1 root root 805 1月 1 22:38 /etc/fstab
[root@Master sh]# echo $$
1693
#$!讲解
[root@Master sh]# tar -zcf etc.tar.gz /etc/ &
[1] 1798
[root@Master sh]# tar: 从成员名中删除开头的“/”
[root@Master sh]# echo tar: 从硬连接目标中删除开头的“/”
$!
1798
[1]+ Done tar -zcf etc.tar.gz /etc/
read命令-->常用
作用:接受键盘输入的信息
语法:
- read 【选项】 变量名(后面写什么就是什么变量)
选项
- -p:提供提示信息-->等待用户按照提示输入信息
- -t:描述-->等待多少秒,用户要输入信息
- -s:隐藏输入的数据-->不能给别人看到的信息
- -n:指定你只能输入多少个参数
read命令
作用:接受键盘输入的信息
语法:
read 【选项】 变量名(后面写什么就是什么变量)
选项
-p:提供提示信息-->等待用户按照提示输入信息
-t:描述-->等待多少秒,用户要输入信息
-s:隐藏输入的数据-->不能给别人看到的信息
-n:指定你只能输入多少个参数declare命令
- 作用:声明变量类型
- 我们都知道a=10--->这个表示a赋值的是10的字符串
- 所以如果我们声明这个变量是数值的话可以直接声明这个数值
语法:
- declare 【+/-】 【选项】 变量名
选项:
- -:代表是设定变量类型
- +:取消定义的变量类型
- -a:数组变量类型
- -i:整数型变量
- -r:只读变量,这个一旦定义了就无法修改-->重启系统释放变量
- -x:把变量声明为环境变量-->相当于export命令
#定义两个数值a b
[root@Master sh]# a=1
[root@Master sh]# b=2
[root@Master sh]# c=$a+$b
[root@Master sh]# echo $c #这里就代表是字符串类型了,所以输出c的值的时候直接输出1+2
1+2
#它只会原封不动输出-->不会自己进行运算
#那么声明一下变量类型
[root@Master sh]# declare -i cc=$a+$b
[root@Master sh]# echo $cc #这里就是声明了是数值型的了
3
#如何理解数组变量类型?
数组可以保存多个值-->理解成一个空间有好多个看成一个整体
举个例子:
[root@Master sh]# declare -a name[0]="135" #中括号里面是脚标
[root@Master sh]# declare -a name[1]="246" #这个代表name1组的值是多少
[root@Master sh]# declare -a name[2]="789"
#如何调用数组型变量?
[root@Master sh]# echo ${name[*]} #需要${组名【*】} *代表所有的数组脚标
135 246 789
数组脚标是从0开始
如果仅仅调用其中一个数组就把*改成脚标号
第三:如果看到名字[] 这个格式的基本上默认视为数组
#查询变量
[root@Master sh]# declare -p
#升级为环境变量
[root@Master sh]# declare -x test
相当于-->[root@Master sh]# export test
#不做操作的时候可以任意修改test的值
[root@Master sh]# echo $test
123
[root@Master sh]# test=222
[root@Master sh]# echo $test
222
#设定为只读属性
[root@Master sh]# declare -r test #这时候就无法动这个test的值
[root@Master sh]# echo $test
222
数值运算
数值运算的方法:
1)declare 【+/-】 【选项】 【变量名】
- declare -i d=$a + $b
2)expr命令:
- d=$(expr $a + $b)
- +号两侧需要加上空格==>这个固定格式
3)let命令:
- let d=$a + $b
4)$(( 运算方式 ))
- d=$(( $a+$b))
5)$[运算式] ---》这个很少用
运算符:
- +-*/:加减乘除
- %:取余数
- ==:等于
- !=:不等于
例子:
bb=$(( (12+2) *(9/3) )) --->先计算小括号的,然后再算乘法
数值算法:
#简单的脚本
[root@Master sh]# vim count.sh
#!/bin/bash
#used jiajianchengchu
value=$(( $1 $2 $3 )) #$1输入的第一个参数
echo $value
#执行以下
[root@Master sh]# chmod a+x count.sh
[root@Master sh]# ./count.sh 11 + 22
33
#第一个问题:用户无法知道输入数字多少个?
#第二个问题:如何知道或者如何判断你是否执行了?
重新编写:
[root@Master sh]# vim count.sh
#!/bin/bash
#used jiajianchengchu
read -t 30 -p "请写入数字:" num1
read -t 30 -p "请写入第二个数字:" num2
read -t 30 -p "请输入加减乘除[+-*/:]" oper
echo -e "\n"
[ "$oper" == "+" ] && echo "$(( $num1 + $num2 ))" && exit
[ "$oper" == "-" ] && echo "$(( $num1 - $num2 ))" && exit
[ "$oper" == "*" ] && echo "$(( $num1 * $num2 ))" && exit
[ "$oper" == "/" ] && echo "$(( $num1 / $num2 ))" && exit
echo "请输入正确的运算符:[+-*/]"
#先用read接受一下用户的输入-->相隔30秒-->指定输入信息
然后:
[] -->代表的是判断-->oper变量的值是否等于+-*/这些运算
&&:代表的是逻辑与-->前面执行正确,后面才能执行运算
$((数值运算的表达式))
exit:如果执行成功了就退出-->结合了&&逻辑与判断哦
#执行查看一下
[root@Master sh]# ./count.sh 11 * 2
请写入数字:11
请写入第二个数字:2
请输入加减乘除[+-*/:]*
22
[root@Master sh]# ./count.sh
请写入数字:55
请写入第二个数字:66
请输入加减乘除[+-*/:]df #如果我这里随便写-->思路得清晰
请输入正确的运算符:[+-*/]变量测试与内容置换-->不好记
变量置换方式 | 变量y没有设置 | 变量y为空 | 变量y设置值 |
x=${y-新值} | x=新值 | x为空 | x=$y |
x=${y:新值} | x=新值 | x=新值 | x=$y |
x=${y+新值} | x为空 | x=新值 | x=新值 |
x=${y:+新值} | x为空 | x为空 | x=新值 |
x=${y=新值} | x=新值 y=新值 | x为空 y值不变 | x=$y y值不变 |
x=${y:=新值} | x=新值 y=新值 | x=新值 y=新值 | x=$y y值不变 |
x=${y?新值} | 新值输出到标准错误输出(就是屏幕) | x为空 | x=$y |
x=${y:?新值} | 新值输出到标准错误输出 | 新值输出到标准错误输出 | x=$y
|
这个很难记忆、用到的时候回到来再翻看
[root@Master sh]# x=${z-new}
[root@Master sh]# echo $x
new
[root@Master sh]# z=123
[root@Master sh]# x=${z-new}
[root@Master sh]# echo $x
123配置文件讲解
source命令:
语法:
- source 配置文件-->让配置文件从新生效
- . 配置文件
[root@Master sh]# source /etc/profile
/etc/profile
- 全局的环境变量
- USER变量:登陆的用户使用的变量
- LOGNAME变量:登陆的用户名
- MAIL:用户邮箱
- PATH:命令的路径
- HOSTNAME:主机名
- HISTSIZE:历史命令的大小
- UMASK:umask的默认值
/etc/profile.d/*.sh
放到这下的脚本都会开机启动
[root@Master sh]#
[root@Master sh]# ls /etc/profile.d/
colorls.csh cvs.csh glib2.csh lang.csh less.csh qt.csh vim.csh which2.sh
colorls.sh cvs.sh glib2.sh lang.sh less.sh qt.sh vim.sh
lang.sh:是默认的系统语言--->直接调用的是/etc/sysconfig/i18n
[root@Master sh]# cat /etc/sysconfig/i18n
LANG="zh_CN.UTF-8"/etc/bashrc
PS1变量修改在这个文件中
~/.bash_profile
[root@Master sh]# cat ~/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then #先判断有没有这个.bashrc,有就加载这个文件
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin #再加载一下PATH,变量叠加,把家目录下的bin目录也加载下去
export PATH #然后在声明成全局变量~/.bashrc
[root@Master sh]# cat ~/.bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i' #定义了一些命令别名
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then #然后再判断一下这个文件,有的话呢就加载这个文件,
. /etc/bashrc
fi
问题1:命令提示符改变
第一点:
在/etc/bashrc文件中==>PS1= 这个定义就是命令提示符的格式
[root@Master sh]# vim /etc/bashrc
注释掉这行看看
# [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
[root@Master sh]# . /etc/bashrc
然后命令提示符直接改变
[root@Master sh]# su
bash-4.1# /etc/issue
作用:shell登陆信息
bash-4.1# cat /etc/issue
CentOS release 6.8 (Final)
Kernel \r on an \m
#kernel的参数
\d:系统日期
\s:操作系统名字
\l:登陆的终端号
\m:系统硬件平台
\n:主机名
\o:显示域名
\r:内核版本
\t:当前系统时间
\u:登陆用户的序列号/etc/issue.net
远程登录的时候显示登陆前的信息
bash-4.1# vim /etc/issue.net
CentOS release 6.8 (Final)
Kernel \r on an \m
#因为通过ssh登陆的,所以修改一下服务端的ssh配置文件
bash-4.1# vim /etc/ssh/sshd_config
#添加这一行
#Banner none
Banner /etc/issue.net
#重启一下sshd服务
bash-4.1# service sshd restart
停止 sshd: [确定]
正在启动 sshd: [确定]
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
CentOS release 6.8 (Final)
Kernel \r on an \m
Last login: Tue Jan 5 22:05:18 2021 from 192.168.75.1
-bash-4.1# /etc/motd
显示登陆后的信息
一般是写着警告信息
-bash-4.1# vim /etc/motd
please used carefully
#远程登录或者是本地登录都可以看到
please used carefully
-bash-4.1# 问题2:查看系统中的快捷键
使用的是stty命令
-bash-4.1# stty -a
speed 38400 baud; rows 23; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
三、结束
“登山则情满于山,观海则意溢于海”
互勉~!