shell 第二章 变量和引用

深入认识变量

什么是变量
  • 变量是在程序中保存用户数据的一段内存存储空间,变量名是内存空间的首地址
变量的名称
  • 组成:字母、数字、下划线组成,不能以数字开头

  • 变量名称的长度,shell没有明确规定,但是为了增加可读性,建议使用较短的、见名知意的名称命名

  • 规则

    • 首字符必须为字母:a-z,A-Z

    • 中间不能由空格,可以使用下划线(_)

    • 不能使用标点符号

    • 不能使用bash中关键字,输入help查看bash的保留字

    • 例:下面的变量名都是很好的选择

复制代码
[root@server ~]# JAVA_HOME=/usr/bin/jvm/jre-1.6.0-openjdk.x86_64
[root@server ~]# SUM=0
[root@server ~]# back_up=/root
变量的类型
  • 原则:shell是一种动态类型语言和弱类型语言,变量是不分数据类型的,统一都使用字符串存储,但根据变量的上下文环境,允许程序执行一些不同的操作,如:比较、整数加减

  • shell的变量数据类型

复制代码
[root@server ~]# vim  test1.sh
​
#!/bin/bash
​
# 定义变量x,输入初始值123
x=123
​
# 变量x加1
​
let "x+=1"
​
# 输出变量x的值
echo  "x=$x"
​
# 替换x中1的值为abc,并赋值给变量y
y=${x/1/abc}
​
# 使用declare  -i  声明变量y为整型变量(-i 表示整型)
declare  -i  y
​
# 输出y的值
echo  "y=$y"
​
[root@server ~]# bash  test1.sh 
x=124
y=abc24
变量的定义
  • 原则:直接使用,不需要变量声明

  • 格式:变量名=变量的值

  • 例:

复制代码
[root@server ~]# vim  test2.sh
​
#!/bin/bash
# 定义变量a
a=1
​
# 定义变量b
b="hello"
​
# 定义变量c
c="hello world"
​
# 定义路径
bak_dir=/data/backup
  • = 前后不能收空格
复制代码
[root@server ~]# a= 3
bash: 3: command not found...
[root@server ~]# b =5
bash: b: command not found...
  • 字符串类型建议使用双引好作为定界符引起,尤其是字符串中有空格
复制代码
[root@server ~]# stu_name=zhang san
bash: san: command not found...
[root@server ~]# stu_name="zhang san"
[root@server ~]# stu_name='zhang san'
自定义变量
  • 概念:上述以赋值形态形成的变量定义形式称为自定义变量

  • 引用变量的值:

    • $变量名

    • ${表达式或变量名}

    • 例:

复制代码
[root@server ~]# a=1024
[root@server ~]# echo $a
1024
[root@server ~]# echo  ${a}
1024
  • 查看变量
复制代码
[root@server ~]# set
[root@server ~]# declare
  • 取消变量:unset 变量名
复制代码
[root@server ~]# a=256
[root@server ~]# echo  $a
256
[root@server ~]# unset  a
[root@server ~]# echo  $a
  • 作用范围:只在当前shell起效
环境变量
  • 环境变量又称为全局变量,可以在任意子shell生效,环境变量又分为自定义环境变量和bash内置的环境变量,用户退出命令后改变量会丢失,若需要永久保存就必须写在文件中

  • 定义环境变量

复制代码
# 法1
export  环境变量=值
复制代码
# 法2
变量名=值
export  变量名
复制代码
# 法3
declare  -x   变量名=值
  • 例:
复制代码
[root@server ~]# export  back_dir1=/home/backup
[root@server ~]# NAME="zhang san"
[root@server ~]# export  NAME
[root@server ~]# declare  -x  AGE=20
[root@server ~]# env   # 显示当前用户的环境变量
[root@server ~]# printenv  # 同上
[root@server ~]# export  # 同上
  • 注意:以上定义的环境变量都是临时的,重启后会失效,若要永久生效,则需要写入到配置文件中

  • 对比:

复制代码
C语言      局部变量      全局变量
shell     自定义变量     环境变量
  • shell 环境变量存储的文件:

    • bash shell 初始化文件有:/etc/profile、 ~/.bash_profile、 ~/.bash_login、 ~/.profile、 ~/.bashrc、/etc/bashrc

    • 如图:

    • /etc/profile :存放一些全局(共有)变量,不管哪个用户,登录时都会读取该文件。通常设置一些Shell变量PATH,USER,HOSTNAME和HISTSIZE等

    • ~/.bash_profile:每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次,默认情况下,此文件通过脚本执行同目录下用户的.bashrc文件

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

    • /etc/bashrc:为每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被读取

    • /etc/inputrc文件为特定的情况处理键盘映射

    • 执行顺序:/etc/profile-->/etc/profile.d/*.sh--> ~/.bash_profile -->/etc/bashrc-->~./.bashrc

    • 结论:

      • 对于用户的环境变量设置,常见的是用户家目录下的.bashrc和.bash_profile

      • 对于全局环境变量设置,常见的文件有:/etc/profile /etc/bashrc /etc/profile.d 这三个配置文件,常用方法是直接在/etc/profile文件中写入全局变量,如果想要在登陆后初始化或者显示加载的内容,只需要把脚本文件放在 /etc/profile.d 文件下即可

位置变量
  • 概念:当一条命令或脚本执行时,后面可以跟多个参数,可以使用位置变量来表示该参数
复制代码
bash  test1.sh  hello  world  123  456
  • 当执行test1.sh 脚本时,第一个参数为hello到第四个参数可以使用特殊的符号表示,如:1 2 $3 ......

  • 常见的位置变量

复制代码
$0 : 脚本名
$1-$9 : 1-9个参数
${10} :10以上的参数需要大花括号括起
$* : 所有参数
$@ : 所有参数
$# : 参数个数
$$ : 当前进程的PID
$! : 上一个后台进程的PID
$? : 上一个命令的返回值状态码,0为成功
  • 例:
复制代码
[root@server ~]# vim  test3.sh
#!/bin/bash
​
echo  "第2个位置参数是: $2"
echo  "第1个位值参数是: $1"
echo  "第4个位置参数是: $4"
echo  "所有参数是: $*"
echo  "所有参数是: $@"
echo  "参数的个数是: $#"
echo  "当前进程的PID值: $$"
​
[root@server ~]# bash  test3.sh 1 2 3 4 5
第2个位置参数是: 2
第1个位值参数是: 1
第4个位置参数是: 4
所有参数是: 1 2 3 4 5
所有参数是: 1 2 3 4 5
参数的个数是: 5
当前进程的PID值: 2986
复制代码
[root@server ~]# vim  test4.sh
​
​
[root@server ~]# bash test4.sh  孙小帅  18  123456@qq.com
name: 孙小帅
age: 18
E-mail:123456@qq.com
  • \* 与 @区别
复制代码
当$* 和 $ @没有被引用的时候,它们确实没有什么区别,都会把位置参数当成一个个体, "$*"会把所有位置参数当成一个整体(或者说当成一个单词),如果没有位置参数,则"$* "为空,如果有两个位置参数并且IFS为空格时,"$*"相当于"$1 $2"
复制代码
"$@"会把所有位置参数当成一个单独的字段,如果没有位置参数($#为0),则"$@"展开为空(不是空字符串,而是空列表),如果存在一个位置参数,则"$@"相当于"$1",如果有两个参数,则"$@"相当于"$1" "$2"等等
复制代码
[root@server ~]# set  --  I am test  command
[root@server ~]# for  i  in  "$@"; do  echo  $i; done
I
am
test
command
[root@server ~]# for  i  in  "$*"; do  echo  $i; done
I am test command

变量赋值和作用域

显示赋值:变量名=变量值
  • 例:
复制代码
ip1=192.168.1.251
school="Peking University"
today1=`date +%F`  # 注意为反引号``
today2=$(date +%F)
read 从键盘读入变量值
  • read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量

  • 格式:read -参数 变量名

  • 参数

    • -p "提示语句:" 屏幕打印出一行提示语句。

    • -n数字:当输入的字符数目达到预定数目时,自动退出,并将输入的数据赋值给变量,如:-n1 , 只要接受到一个字符就退出。只要按下一个字符进行回答,read命令立即接受输入并将其传给变量。无需按回车键

    • -t 等待时间 :计时输入,使用read命令存在着潜在危险。脚本很可能会停下来一直等待用户的输入。如果无论是否输入数据脚本都必须继续执行,那么可以使用-t选项指定一个计时器。-t选项指定read命令等待输入的秒数。当计时满时,read命令返回一个非零退出状态

    • -s : 关闭回显,使read命令中输入的数据不显示在监视器上(实际上,数据是显示的,只是read命令将文本颜色设置成与背景相同的颜色)

    • 常用格式:

复制代码
read  变量名
read  -p  "提示信息:"   变量名
  • 例:
复制代码
[root@server ~]# read  -p  "Enter  Numbers: "  num
Enter  Numbers: 9527
[root@server ~]# echo  $num
9527
[root@server ~]# read  -t  3  n1    # 不要输入内容,等待3秒后自动结束输入
[root@server ~]# read  -s  -p  "Enter your password: "  passw
Enter your password: [root@server ~]# echo  $passw 
123456
​
[root@server ~]# echo  $REPLY
​
[root@server ~]# read
100
[root@server ~]# echo  $REPLY   # 当输入时没有指定变量接收,会默认存储到REPLY变量中
100
​
# 一次性输入多个变量的值
[root@server ~]# read  t1  t2
12 35
[root@server ~]# echo  $t1 $t2
12 35
  • 面试题:总结4中赋值方式
复制代码
1.直接赋值:name="li si"
2.read命令: read  name
3.使用位置参数($1 $2 $3…) : name=$1
4.命令输入:name=$(whoami)  
变量和引号
  • 双引号:除了$ 、单引号、反引号、反斜线之外,其它被引起的内容保持字面意思

  • 单引号:所有字符保持字面意思

  • 反引号:被引起的字符串转为shell命令

  • 反斜线:转义符(\),屏蔽后面字符的特殊含义

变量的作用域
  • 全局变量:全局变量定义在脚本中,也可以定义在函数中,作用范围:从定义的开始处到shell脚本结束或者被显示的去除

  • 例:

复制代码
[root@server ~]# vim  test5.sh
​
#!/bin/bash
​
func()   # 定义函数
{
        echo   "$v1"
        v1=200
}
v1=100
func
echo  "$v1"
​
​
[root@server ~]# bash  test5.sh 
100
200
  • 函数内部定义全局变量
复制代码
# 上例修改
[root@server ~]# vim  test5.sh
#!/bin/bash
​
func()   # 定义函数
{
        v2=200
}
func
echo  "$v2"
​
​
[root@server ~]# bash  test5.sh 
200
  • 局部变量:范围更小,仅限于某个程序段中,如:函数、shell等,通过local关键字定义,注意:函数的参数也是局部变量
复制代码
# 上例修改
[root@server ~]# vim  test5.sh
​
#!/bin/bash
​
func()   # 定义函数
{
        local v3=200  # 使用local关键字声明为局部变量
}
func
echo  "$v3"
[root@server ~]# bash  test5.sh 
​
  • 全局变量和局部变量区别
复制代码
# 上例修改
[root@server ~]# vim  test5.sh
​
#!/bin/bash
func()
{
        #输出全局变量v1的值
        echo "global variable v1 is $v1"
        #定义局部变量v1
        local v1=2
        #输出局部变量v1的值
        echo "local variable v1 is $v1"
}
​
#定义全局变量v1
v1=1
#调用函数
func
#输出全局变量v1的值
echo "global variable v1 is $v1"
变量的运算
  • 运算符与命令
  • 示例1:
复制代码
[root@server ~]# expr  1 + 1  # 注意+左右必须要有空格
2
[root@server ~]# expr  1+1    # 否则原样显示
1+1
[root@server ~]# a=1
[root@server ~]# b=2
[root@server ~]# expr  $a + $b  # 支持变量
3
[root@server ~]# let  num=1+2   # let+echo 等价于expr
[root@server ~]# echo  $num
3
[root@server ~]# let num=1 + 2   # 注意let中运算符左右不能由空格
-bash: let: +:语法错误: 需要操作数 (错误符号是 "+")
[root@server ~]# echo  $((1+2))
3
[root@server ~]# echo  $((5%3))
2
[root@server ~]# echo  $((3%5))
3
[root@server ~]# echo  $((1-5))
-4
[root@server ~]# echo  $((2 * 5))   # 可以有空格
10
[root@server ~]# echo  $((5.2-5))   # 只支持整数运算
-bash: 5.2-5:语法错误: 无效的算术运算符 (错误符号是 ".2-5")
[root@server ~]# echo  $[2+3]   # []  等价于 (())
5
[root@server ~]# echo  $[2.5+3]  #  # 只支持整数运算
-bash: 2.5+3:语法错误: 无效的算术运算符 (错误符号是 ".5+3")
复制代码
[root@server ~]# bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
1.1+2
3.1
2.5-3.9
-1.4
1.5>4
0
5>3
1
quit  # 退出交互模式
​
# 不进入交互模式直接使用,bc需要放在最后
[root@server ~]# echo  "scale=3;11/3"  | bc   
3.666
# scale=3 表示保留运算精度
  • 示例2
复制代码
# 返回变量长度
[root@server ~]# str1="hello world"
[root@server ~]# echo  ${#str1}
11
复制代码
# 变量截取
[root@server ~]# echo  ${str1:0:3} # 从左边第1个字符开始截取3个
hel
​
[root@server ~]# echo  ${str1::3}  # 可以省略起始0
hel
​
[root@server ~]# echo  ${str1:1}  # 从下标1开始截取到尾部
ello world
​
[root@server ~]# echo  ${str1:0-1:1}  # 从右边第一个字符开始截取1个,左边第一个为0,右边第一个为0-1
d
​
[root@server ~]# echo  ${str1:0-5} # 从右边第5个开始截取到尾部
world
[root@server ~]# echo  ${str1: -5} # 使用空格替代0,同上
world
​
[root@server ~]# echo  ${str1:-5} # 没有空格表示提取整串
hello world
复制代码
# 使用%截取,删除右边字符,保留左边字符
[root@server ~]# filename=testfile.tar
[root@server ~]# file=${filename%.*}  # %.表示从右边开始检索第一次出现. 之后删除.右侧的内容,保留左边内容,用于对文件名去掉扩展名
[root@server ~]# echo  $file
testfile
​
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url%%:*} # %%: 表示从右边开始检索最后一次出现的: 之后删除:右侧的内容,保留左边内容
[root@server ~]# echo  $ul1
http
​
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url#*.}  # #*.表示左向右遍历,删除第一次出现的.左侧内容
[root@server ~]# echo  $ul1
baidu.com/index.html
​
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url%/*}
[root@server ~]# echo  $ul1
http://www.baidu.com
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url##*/}
[root@server ~]# echo  $ul1
index.html
  • 特殊扩展
  • -示例:如果parameter变量值为空或未赋值,则返回word字符串的值,注意:parameter变量值不变
复制代码
[root@server ~]# echo  $var1
​
[root@server ~]# var2=${var:-hello}
[root@server ~]# echo  $var2
hello
​
  • -示例:如果parameter变量有值,则返回parameter变量值
复制代码
[root@server ~]# var2=${var1:-world}
[root@server ~]# echo $var2
hello
  • =示例:如果parameter变量有值,则返回parameter变量值
复制代码
[root@server ~]# unset  var1  var2
[root@server ~]# var1=hello
[root@server ~]# var2=${var1:=world}
[root@server ~]# echo $var2
hello
  • ?示例:如果parameter变量值为空或未赋值,则word字符串会作为标准错误输出,否则输出变量的值
复制代码
[root@server ~]# unset  var1  var2
[root@server ~]# var2=${var1:?world}
-bash: var1: world  # 标准错误输出
[root@server ~]# unset  var1  var2
[root@server ~]# var1=hello
[root@server ~]# var2=${var1:?world}
[root@server ~]# echo $var2
hello
  • +示例:如果parameter变量值为空或未赋值,则什么都不做,否则word字符串将替代变量的值
复制代码
[root@server ~]# unset  var1  var2
[root@server ~]# var2=${var1:+world}
[root@server ~]# echo  $var2
​
[root@server ~]# unset  var1  var2
[root@server ~]# var1=hello
[root@server ~]# var2=${var1:+world}
[root@server ~]# echo  $var1 $var2
hello world
  • 面试题:删除7天前的过期备份数据
复制代码
#!/bin/bash
find  ${path:-/tmp}   -name  "*.tar.gz"  -type  f -mtime +7  |  xargs rm  -f
​
​
# find为查找文件命令
# ${path:-/tmp} :表示如果没有定义path则使用/tmp替代
# 使用xargs命令表示管道符进行数据转换

第三章 shell条件测试

用途

  • 为了能够正确处理Shell程序运行过程中遇到的各种情况,Linux Shell提供了一组测试运算符。

  • 通过这些运算符,Shell程序能够判断某种或者几个条件是否成立。

  • 条件测试在各种流程控制语句,例如判断语句和循环语句中发挥了重要的作用,所以了解和掌握这些条件测试是非常重要的

基本语法

格式:
复制代码
格式1: test  -参数  条件表达式
格式2: [  条件表达式  ]     # 注意:[]的左右要有空格   
​
格式3: [[  条件表达式  ]]   # 注意:[]的左右要有空格
格式4: ((条件表达式))
  • test单独使用,判断条件为真,echo $?返回0,假返回1

  • test与 等价

  • \[ ] 是扩展命令,可以使用通配符等进行模式匹配,&& || > < 等操作符可以直接应用于双中括号中,但不能用于单中括号中

  • (()) 一般用于if语句里,两端不需要有空格,测试对象为整数

示例
复制代码
# test语法
[root@server ~]# test -f  /etc/passwd
[root@server ~]# echo  $?
0
[root@server ~]# test -f  /etc/aa
[root@server ~]# echo  $?
1
[root@server ~]# 
[root@server ~]# test  -f  /etc/passwd  &&  echo  1 || echo  0
1
[root@server ~]# test  -f  /etc/aa  &&  echo  1 || echo  0
0
[root@server ~]# test  -f  /etc/passwd  &&  echo  yes || echo  no
yes
[root@server ~]# test  -f  /etc/aa  &&  echo  yes || echo  no
no
[root@server ~]# if  test -f /etc/passwd ; then  echo  1 ; else echo no ;fi
1
[root@server ~]# if  test -f /etc/aa ; then  echo  1 ; else echo no ;fi
no
复制代码
# [] 语法
[root@server ~]# [-f  /etc/passwd]    # 注意:[] 中要有空格
bash: [-f: command not found...
​
[root@server ~]# [  -f  /etc/passwd ]
[root@server ~]# echo  $?
0
[root@server ~]# [  -f  /etc/aa ]
[root@server ~]# echo  $?
1
[root@server ~]# [  -f  /etc/aa ] &&  echo  y  ||  echo  n
n
[root@server ~]# [  -f  /etc/passwd ] &&  echo  y  ||  echo  n
y
[root@server ~]# if  [ -f /etc/passwd ] ; then  echo  1 ; else echo no ;fi
1
[root@server ~]# if  [ -f /etc/aa ] ; then  echo  1 ; else echo no ;fi
no
复制代码
# [[]]  语法
[root@server ~]# [[ 3 > 2 || 1 > 2 ]]  &&  echo  1 || echo 0
1
[root@server ~]# [[ 3 > 2 && 1 > 2 ]]  &&  echo  1 || echo 0
0
复制代码
(()) 语法
[root@server ~]# ((9>5))  &&  echo 1  || echo 0
1
[root@server ~]# (( 9 > 5 ))  &&  echo 1  || echo 0
1
[root@server ~]# ((9>5))  &&  echo 1  || echo 0
1
[root@server ~]# ((9>13))  &&  echo 1  || echo 0
0
​
[root@server ~]# ((9>13.5))  &&  echo 1  || echo 0  # 注意:不支持小数运算
-bash: ((: 9>13.5:语法错误: 无效的算术运算符 (错误符号是 ".5")
0

文件测试

参数:
参数 作用
-b 文件名 检测文件是否是块设备文件,是返回 true
-c 文件名 是否是字符设备文件
-d 文件名 是否是目录
-f 文件名 是否是普通文件(既不是目录,也不是设备文件)
-S 文件名 是否为socket文件
-P 文件名 是否为管道符文件
-L 文件名 是否为链接文件
-u 文件名 是否有suid的权限
-s 文件名 是否为空(文件大小是否大于0),不为空返回 true
-e 文件名 检测文件(包括目录)是否存在,如果是,则返回 true
-r 文件名 检测文件是否可读,如果是,则返回 true。
-w 文件名 检测文件是否可写,如果是,则返回 true
-x 文件名 检测文件是否可执行,如果是,则返回 true
f1 -nt f2 文件f1比文件f2新则为真(根据文件修改时间计算)
f1 -ot f2 文件f1比文件f2旧则为真(根据文件修改时间计算)
示例
复制代码
[root@server ~]# [ -d /root ] && echo  y || echo n
y
[root@server ~]# [ -d /aa ] && echo  y || echo n
n
[root@server ~]# [ -b /dev/nvme0n1 ] && echo  y || echo n
y
[root@server ~]# [ -L /dev/cdrom ] && echo  y || echo n
y
[root@server ~]# ll  /dev/cdrom 
lrwxrwxrwx 1 root root 3  3月 22 11:31 /dev/cdrom -> sr0
[root@server ~]# [ -e /file1 ] && echo  y || echo n
n
[root@server ~]# touch  /file1
[root@server ~]# [ -e /file1 ] && echo  y || echo n
y
复制代码
# 编写脚本,测试文件是否存在,不存在则创建
[root@server ~]# vim  temp1.sh
#!/bin/bash
​
FILE=$1
echo  FILE
​
if test -e $FILE
then
        echo  "$FILE文件已存在"
else    
        echo  "$FILE文件不存在,开始新建..."
        touch  $FILE
        ls  -l $FILE
fi 
​
[root@server ~]# bash temp1.sh  /etc/passwd
/etc/passwd
/etc/passwd文件已存在
[root@server ~]# bash temp1.sh  temp
temp
temp文件不存在,开始新建...
-rw-r--r-- 1 root root 0  6月 17 14:53 temp
复制代码
# 上例改写
[root@server ~]# vim  temp1.sh
#!/bin/bash
​
read -p "请输入文件名: "  FILE
​
if test -e $FILE
then
        echo  "$FILE文件已存在"
else
        echo  "$FILE文件不存在,开始新建..."
        touch  $FILE
        ls  -l $FILE
fi
​
[root@server ~]# bash temp1.sh
请输入文件名: /etc/sos/sos.conf
/etc/sos/sos.conf文件已存在
[root@server ~]# bash temp1.sh
请输入文件名: t1
t1文件不存在,开始新建...
-rw-r--r-- 1 root root 0  6月 17 14:56 t1

整数测试

作用
  • 用于比较两个数值的大小关系,操作的对象是数值
操作符
示例
复制代码
[root@server ~]# [ 5 -gt 3 ] && echo y || echo n  
y
n
[root@server ~]# test  5 -gt 3  && echo y || echo n  
y
[root@server ~]# ((5>3))  && echo y || echo  0
y
复制代码
# 知识拓展
# 检查左侧内容是否包含右侧的表达式,可以使用 =~ 正则匹配,表示是否包含
[root@server ~]# n=123
[root@server ~]# [[ "$n"  =~ ^[0-9]+$  ]]  && echo  y  || echo  n
y
[root@server ~]# n=123ttt
[root@server ~]# [[ "$n"  =~ ^[0-9]+$  ]]  && echo  y  || echo  n
n

逻辑操作符

符号
例:
复制代码
[root@server ~]# [ -f /etc/passwd  -a -f /etc/services ] && echo  1 || echo 0
1
[root@server ~]# [ -f /etc/hosts  -o  -d /etc/services ] && echo  1 || echo 0
1
[root@server ~]# ((5<10 && 5>2))  && echo y || echo n
y
[root@server ~]# ((2<5<10))  && echo y || echo n
y
[root@server ~]# ((2<5<1))  && echo y || echo n
n
[root@server ~]# ((6<5<10))  && echo y || echo n
y
[root@server ~]# ((2<5<-1))  && echo y || echo n
n

命令分隔符

复制代码
cmd1;cmd2     以独立的进程依次执行cmd1和cmd2
(cmd1;cmd2)   在同一进程中依次执行cmd1和cmd2
cmd1&cmd2     cmd1和cmd2同时执行,分属于不同的进程
cmd1&&cmd2    当cmd1为真时,则执行cmd2
cmd1||cmd2    当cmd1不为真时,则执行cmd2
cmd&          后台执行
复制代码
# 若账户fox10不存在,则添加账户
[root@server ~]# id fox10  &>  /dev/null  &&  echo  "fox10已存在"  ||  useradd  fox10
​
# &>  /dev/null 表示将左侧命令执行的正确和错误输出到“黑洞”即不显示到屏幕

案例分析

  • 例1:判断当前已登录账户数,若超过5个则输出"Too many"
复制代码
[root@server ~]# num=$(who | cut -d " " -f1 | sort -u | wc -l)
​
[root@server ~]# [ $num -gt 5 ] && echo "Too many" || echo "已登录账户数:$num"
已登录账户数:1
​
# who : 查看当前已登录的账户信息
​
# cut -d " " -f1 :以空格为列向分割符,截取第1部分
​
# sort -u :去重后排序
​
# wc  -l:计算行数
​
# 上例改写为:
[root@server ~]# (($num>5))  && echo "Too many" || echo "已登录账户数:$num"
  • 例2:编写脚本temp2.sh ,程序从键盘读入一个目录名,判断该命令是否存在,若不存在则创建,并显示目录信息
复制代码
[root@server ~]# vim  temp2.sh
#!/bin/bash
​
cd  /
ls
read -p "请输入一个目录名:"  dir
test  -d  $dir  &&  ls  -l  $dir  || (echo "目录不存在,开始新建..." ; mkdir  $dir ; ls -l $dir)
  • 例3:如果/var/log/messages文件行数大于30行,则显示提示信息
复制代码
[root@server ~]# (($(cat  /var/log/messages | wc -l)>30)) && echo  "好大一个文件" || echo  "还能接受"
  • 例4:编写脚本temp3.sh,功能:显示root目录下的文件信息,之后建立一个aa目录,在aa目录下新建一个文件bb.txt,并修改该文件的权限为可执行,最后再次浏览信息
复制代码
[root@server ~]# vim  temp3.sh
#!/bin/bash
​
ls -l /root
​
mkdir  /root/aa
​
touch  /root/aa/bb.txt
​
chmod  +x  /root/aa/bb.txt
​
ls -l /root
复制代码
[root@server ~]# vim  temp4.sh
#!/bin/bash
​
read -p "请输入x的值:" x
​
read -p "请输入y的值:" y
​
if  [ -n "$x" -a  -n  "$y" ]  # -n判断非空
then
        if  [[ "$x" =~ ^[0-9]+$ ]]  &&  [[ "$y" =~ ^[0-9]+$ ]] # 判断是数字
        then
                echo  $[x+y]
        else
                echo  "请输入数字"
        fi
else
        echo "请输入有效内容"
fi
  • 例6:编写temp5.sh脚本显示所有用户,选择一个用户输入,判断是root账户还是系统账户还是普通账户
复制代码
[root@server ~]# vim  temp5.sh
#!/bin/bash
​
cat /etc/passwd | cut -d ":" -f1 | sort -u
​
read -p "请输入一个账户名:"  us
​
us_num=$(id -u $us)
​
if  (($us_num==0))
then
        echo  "此用户为管理员账户"
else
        if (($us_num>=1 && $us_num<=999))
        then
                echo  "此账户为系统账户"
        else
                echo  "普通账户"
        fi
fi
  • 例7:编写脚本temp6.sh ,给定文件/root/anaconda-ks.cfg,判断是否存在空白行,若存在则显示行数,否则显示"无空白行"提示信息
复制代码
[root@server ~]# vim  temp6.sh
#!/bin/bash
​
num=$(grep  ^$  /etc/root/anaconda-ks.cfg.conf | wc -l)
​
if  (($num>0))
then
        echo  "/etc/root/anaconda-ks.cfg  文件含有空白行,行数:$num,位置如下:"
        grep  -n  ^$  /etc/root/anaconda-ks.cfg.conf
else
        echo  "/etc/root/anaconda-ks.cfg  此文件无空白行"
fi
相关推荐
暗中讨饭xdm1 小时前
立体echarts柱状图咋做
前端·vue.js·echarts
wuhen_n1 小时前
阿里云百炼平台 API 接入教程(附 Node.js + TypeScript 实战)
前端·人工智能·阿里云·ai编程
码语智行1 小时前
操作日志注解模块
java·前端·python
CDN3601 小时前
【前端实战】LCP指标从2.5s优化至0.8s!用360CDN的WebP自适应与缓存策略榨干性能
前端·缓存
星辰_mya1 小时前
ThreadLocal之微服务链路追踪
java·开发语言·前端
会编程的土豆1 小时前
前端和后端是怎么配合工作的(Go后端视角)
前端·golang·状态模式
w_t_y_y1 小时前
vue父子组件通信(一)父子调用和通信(2)VUE3
前端·javascript·vue.js
Demon1_Coder1 小时前
Day1-SpringAI-1.0.0版本
java·开发语言·前端