Linux-shell基础(2)

一、前言

“得道者多助,失道者寡助”

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=LALA

env命令

  • 作用:查看系统的环境变量
  • 和set命令差不多-->都能查看变量
[root@Master ~]# export SHAN="LALA"
[root@Master ~]# env | grep SHAN
SHAN=LALA

PATH环境变量

作用:系统查找命令的路径

默认是用:冒号相隔开

[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 good

PS1环境变量

  • 作用:定义的是命令行的提示符
  • 可以根据需求来修改
  • 永久修改-->写入配置文件/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

 

三、结束

“登山则情满于山,观海则意溢于海”

互勉~!


版权声明:本文为Liang_GaRy原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。