shell脚本变量详解(自定义变量、环境变量、变量赋值、变量运算、变量内容替换)

简介: shell变量shell变量是指用一个特定的字符串去表示不固定的内容1.变量的类型1.1自定义变量一般情况下不怎么使用环境变量,如果需要在其他文件中引入某个文件的变量则在脚本最开始的位置使用source 或者. 执行下该脚本即可

shell变量

shell变量是指用一个特定的字符串去表示不固定的内容

1.变量的类型

1.1自定义变量

一般情况下不怎么使用环境变量,如果需要在其他文件中引入某个文件的变量则在脚本最开始的位置使用source 或者. 执行下该脚本即可

image.png定义变量:变量名=变量值 变量名必须以字母或下划线开头,区分大小写 ip1=127.0.0.1

引用变量:$变量名 或 变 量 名 ( “ ” 花 括 号 另 有 他 意 , 假 如 想 在 变 量 后 面 直 接 加 其 他 内 容 , 这 是 用 花 括 号 会 非 常 方 便 , 同 时 也 有 很 多 功 能 , 例 如 {变量名} (“{}”花括号另有他意,假如想在变量后面直接加其他内容,这是用花括号 会非常方便,同时也有很多功能,例如变量名(“”花括号另有他意,假如想在变量后面直接加其他内容,这是用花括号会非常方便,同时也有很多功能,例如{#变量名}则会输出这个变量的长度)

查看变量:echo $变量名 set(会列出所有变量,包括自定义变量和环境变量)

取消变量:unset 变量名

作用范围:仅在当前shell中有效

自己写的几个脚本

1.1.不使用变量

#!/bin/bash
ping -c3 www.baidu.com &>/dev/null && echo "www.baidu.com is up" ||echo  "www.baidu.com is down"

1.2.使用变量,用特殊符号一行去进行条件测试

#!/bin/bash
IP=www.baidu.com
ping -c3 $IP &>/dev/null && echo "$IP is up" || echo "$IP is down"

1.3.使用if语句做判断

#!/bin/bash
COM=www.baidu.com
if ping -c3 $COM &>/dev/null ;then
echo "$COM is up"
else  
echo "$COM is down"
 fi

1.4.使用条件测试

#!/bin/bash
COM=www.baidu.com
ping -c3 $COM &>/dev/null
if [ $? -eq 0 ];then
echo "$COM is up"
else
echo "$COM is down"
fi

1.5.不适用固定的变量值而是用read命令从键盘获取变量值

#!/bin/bash

read -p "please input a ip: " ip
ping -c3 $ip &>/dev/null
if [ $? -eq 0 ] ; then
echo "$ip is up"
else
echo "$ip is down"

1.2.环境变量

定义环境变量:方法一 export back_dir=/home/backup


方法二 export back_dir 将自定义变量转换成环境变量


引用环境变量:$变量名 或 ${变量名}


查看环境变量 :echo $变量名 env 例如:env | grep back_dir


变量作用范围:在当前shell和子shell有效


1.3.位置变量

$1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}


1.4.预定义变量

$0 脚本名称 默认输出路径加脚本名,可以使用basename来只输出脚本的名称不包含路径,dirname可以输出脚本所在的文件夹名称


$* 所有的参数


$@ 所有的参数


$# 参数的个数


$$ 当前进程的PID


$! 上一个后台进程的PID


$? 上一个命令的返回值,0表示成功



∗ 和 *和∗和@的区别


$*:所有的位置参数被作为一个单词,注意 $* 必须被双引号引用


@ : 与 @:与@:与*同义,但每个参数都是一个独立的""引用字串,这就意味着参数被完整地传递


$@ $* 只在被双引号包起来的时候才会有差异

双引号括起来的情况:

$*将所有的参数认为是一个字段

$@以IFS(默认为空格)来划分字段,如果空格在“”里面,不划分。采用LS的脚本运行./test 1 “2 3” 4 来发现差异


没有括起来的情况是@ 和 @和@和*一样的,见到IFS就划分字段。还是采用LS的脚本运行./test 1 “2 3” 4 来发现差异

1.4.1预定义变量使用脚本

#!/bin/bash
echo "第2个位置参数是$2"
echo "第1个位置参数是$2"
echo "第4个位置参数是$2"
echo "所有参数是: $*"
echo "所有参数是: $@"
echo "参数的个数是: $#"
echo "当前进程的PID是:$$"
echo '1='$1
echo '$2='$2
echo '$3='$3
echo '$*='$*
echo '$@='$@
echo '$#='$#
echo '$$='$$

1.4.2预定义变量位置变量整合脚本

#!/bin/bash
if [ $# -eq 0 ];then
        echo "usage: `basename $0` file"
        exit
fi
if [ ! -f $1 ];then
        echo "error file"
        exit
fi
for ip in `cat $1`
do
        ping -c1 $ip &>/dev/null
        if [ $? -eq 0 ];then
                echo "$ip is up"
        else
                echo "$ip is down"
        fi
done

1.4.3预定义变量批量创建用户

#!/bin/bash
#-----------批量创建用户------------
if [ $# -eq 0 ];then
        echo "usage: `basename $0` file"
        exit
fi
if [  -f $1 ];then
        echo "Began to create a file of the user...."
else
        echo "error file"
fi
for user in `cat user.txt`
do
        useradd $user
        if [ $? -eq 0 ];then
                echo "123" |passwd --stdin $user
        fi
done

2.变量的赋值方式:

2.1.显示赋值

变量名=变量值

实例:

  ip1=192.168.81.250
  school="beijing 1000phone"
  today1=$(date +%F) 或者使用反引号

2.2.read从键盘读入变量值

  read 变量名
  read -p "提示信息:"  变量名
  read -t 5 -p "提示信息:"  变量名     -t代表等待时间,5秒内不输入则退出
  read -n 2 变量名   -n代表限制输入的字符数

read后面可以跟很多变量,例如下图,根据空格将对应的变量赋值 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ESrnCtnb-1590841971204)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200128205106658.png)]


定义或引用变量时注意事项


“” 弱引用 ""双引号中可用使用变量


‘’ 强引用 ''单引号中不可用变量,单引号中输入的啥输出就是啥


很多情况下使用嵌套


例如: name=“jiang xiaolong” ; boy="$name"’ is good!’;echo $boy


`` 命令替换,等价于$()反引号中的shell命令会先被执行

3.变量的运算

3.1.整数运算

方法一:expr

expr  1+2
expr $num1 + $num2    + - \\* / %

方法二:$(())

echo $(($num1+$num2))   + - * / %
echo $((num1+num2))   可用省略括号内的$符号
echo $((5-3*2))   也可以直接用数值进行运算
echo $(((5-3)*2))   第三个括号是数值的简便算法运算
echo $((2**3))      也可以使用整数幂运算
sum=$((1+2));echo $sum    可用赋给变量
#---------------求磁盘使用率---------------------
disk_gen=$(df | grep -v "^文件" |grep '/$'|awk '{print $6}')
disk_gen_used=$(df | grep -v "^文件" |grep '/$'|awk '{print $3}')
disk_gen_total=$(df | grep -v "^文件" |grep '/$'|awk '{print $2}')
disk_gen_percent=$(($disk_gen_used*100/$disk_gen_total))
echo "disk usage rate is $disk_gen_percent"'%'
disk_myscr=$(df | grep -v "^文件" |grep '/my_scripts$'|awk '{print $6}')
disk_myscr_used=$(df | grep -v "^文件" |grep '/my_scripts$'|awk '{print $3}')
disk_myscr_total=$(df | grep -v "^文件" |grep '/my_scripts$'|awk '{print $2}')
disk_myscr_percent=$(($disk_myscr_used*100/$disk_myscr_total))
echo "disk usage rate is $disk_myscr_percent"'%'
if [ $disk_gen_percent -ge 80 ];then
        echo '/磁盘使用率超过80%'
elif [ $disk_myscr_percent -ge 80 ];then
        echo "my_scripts磁盘使用率超过80%"
fi

方法三:$[]

使用方法和方法二类似,只不过括号少了

echo $[5+2]         + - * / %
echo $[5**2]
#-----------------求出内存使用率------------
mem_used=`free -m | grep '^Mem:'|awk '{print $3}'`
mem_total=`free -m | grep '^Mem:'|awk '{print $2}'`
mem_percentage=$[$mem_used*100/$mem_total]
echo "Memory usage rate is $mem_percentage"'%'
if [ $mem_percentafe > 80 ];then
        echo "系统内存使用率超过了80%"
else
        echo "ok"
fi

方法四:let

while循环常用到

let sum=2+3;echo $sum
let i++;echo $i     i++表示i=i+1
#------------------let方法运算---------------
ip=127.0.0.1
i=1
while [ $i -le 5 ]
do
        ping -c1  $ip &>/dev/null
        if [ $? -eq 0 ];then
                echo "$ip is up..."
        fi
        let i++
done

3.2.小数运算

echo "2*4"|bc
echo "2^4"|bc
echo "scale=2;6/4"|bc     scale不可更换成别的,固定参数
awk 'BEGIN{print 1/2}'
echo "print 5.0/2" | python

4.变量内容的删除和替换

4.1.内容的删除

总结:

原变量内容不会修改

*.表示.之前的所有内容

#表示删除到第一个匹配的内容,##表示一直删除到最后一个匹配的内容

4.1.1.从前往后删

url=www.sina.com.cn
echo ${#url}    显示出变量的长度
echo ${url} 标准查看
echo ${url#*.}    从前往后删,删完第一个.之前的所有内容,最短匹配
    输出:sina.com.cn
echo ${url##*.} 从前往后删一直删到最后一个包含.的内容,最长匹配
    输出:cn
[root@192 d02章_Shell变量精讲]# echo ${url}
  www.baidu.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url#www.}
  baidu.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url#www.baidu}
  .com.cn
[root@192 d02章_Shell变量精讲]# echo ${url#www.bai}
  du.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url##www.baidu}
  .com.cn
[root@192 d02章_Shell变量精讲]# echo ${url##www.baidu.com}
  .cn
[root@192 d02章_Shell变量精讲]# echo ${url##*.}
  cn

4.1.2.从后往前删

url=www.sina.com.cn
echo ${url}
echo ${url%.*}    从后往前,最短匹配,删除最后包含.的内容
    输出:www.sina.com
echo ${url%%.*}   从后往前,最长匹配,贪婪匹配,删到最前面包含.的内容
    输出:www
[root@192 d02章_Shell变量精讲]# echo ${url}
www.baidu.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url%.*}
www.baidu.com
[root@192 d02章_Shell变量精讲]# echo ${url%%.*}
www
[root@192 d02章_Shell变量精讲]# echo ${url%%.baidu.com.cn}
www
[root@192 d02章_Shell变量精讲]# echo ${url%%.*}
www
[root@192 d02章_Shell变量精讲]# echo ${url%.cn}
www.baidu.com
[root@192 d02章_Shell变量精讲]# echo ${url%.baidu.cn}
www.baidu.com.cn

4.1.3.从前往后/从后往前再次练习

[root@192 d02章_Shell变量精讲]# echo ${aaa}
jiangxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa%g}    错误,应该是{aaa%g*或者aaa%ga或者*g*},因为g不是最后一个字符
jiangxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa%ga}
jiangxiaolon
[root@192 d02章_Shell变量精讲]# echo ${aaa%a}
jiangxiaolong
[root@192 d02章_Shell变量精讲]# echo ${aaa#a}    错误,应该是{aaa#*a或者aaa#jia或者aaa#*a*},因为a不是最前面的字符
jiangxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa#jia}
ngxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa#*a}
ngxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa##*ao}
longa
[root@192 d02章_Shell变量精讲]# echo ${aaa%a}
jiangxiaolong
[root@192 d02章_Shell变量精讲]# echo ${aaa%longa}
jiangxiao
[root@192 d02章_Shell变量精讲]# echo ${aaa%%xiao*}
jiang
[root@192 d02章_Shell变量精讲]# echo ${aaa%%*xiao*}

4.2.索引及切片

变量值的每一个字符代表一个索引,从0开始

url=www.sina.com.cn
  0123456789.....   索引位
echo ${url:0:5}   取0-5的索引位进行切片,切出www.s
echo ${url:5:5}   取第五位到第五位
echo ${url:5}   取第五位到最后

4.3.内容的替换

url=www.sina.com.cn
echo ${url/sina/baidu}    将sina替换成baidu
echo ${url/n/N}     只将第一个n替换成N
echo ${url//n/N}    贪婪匹配,将所有的n替换成N
#-----------利用替换来求磁盘使用率-----------
cpgzd=/
gen=`df | grep $cpgzd'$'|awk '{print $6}'`
myscripts=`df | grep ${cpgzd/'/'/my_scripts}'$'| awk '{print $6}'`    因为是/所有要把他用强引用引起来取消转义内容
gen_used=`df | grep $cpgzd'$'|awk '{print $3}'`
myscripts_used=`df | grep ${cpgzd/'/'/my_scripts}'$'| awk '{print $3}'`
gen_total=`df | grep $cpgzd'$'|awk '{print $2}'`
myscripts_total=`df | grep ${cpgzd/'/'/my_scripts}'$'|awk '{print $2}'`
gen_percen=$(($gen_used*100/$gen_total))
myscripts_percen=$(($myscripts_used*100/myscripts_total))
echo "/ disk usage rate is $gen_percen"'%'
echo "my_scripts disk usage rate is $myscripts_percen"'%'

4.4.变量的替代

unset var1
echo ${var1}
echo ${var1-aaaaa}      -表示替代的变量值
  aaaaa
var2=111
echo ${var2-bbbbb}
  111
var3=
echo ${var3-ccccc}
${变量名-新的变量值}
变量名没有被赋值:会使用新的变量值替代
变量名有被赋值(包括空值):不会被替代

4.1空值的变量无法被替代很不合理

可以使用:-的形式让空值的变量得到替代

unset var1
unset var2
unset var3
var2=
var3=111
echo ${var1:-aaaaa}   被替代
echo ${var2:-bbbbb}   被替代
echo ${var3:-ccccc}   不会替代
${变量名:-新的变量值}
变量没有被赋值(包括控制):都会使用“新的变量值”替代
变量有被赋值:不会被替代
就好比var1单身可以有对象,var2分过手可以再次拥有对象,var3有对象不能被插足

扩展

unset var1
unset var2
unset var3
var2=111
var3=
echo ${var2+aaaa}   定义过的会被修改
echo ${var3+aaaa}   空值的也会被修改
echo ${var1+aaaa}   没有定义变量值的不会被修改
echo ${var2:+aaaa}    定义过的会被修改
echo ${var3:+aaaa}    空值的不会被修改
echo ${var1:+aaaa}    没有定义变量值的不会被修改
echo ${var1=aaaa}   没有定义变量值的会被修改
echo ${var2=aaaa}   定义过的不会被修改
echo ${var3=aaaa}   空值的也会被修改
echo ${var1:=aaaa}    没有定义变量值的会被修改
echo ${var2:=aaaa}    定义过的不会被修改
echo ${var3:=aaaa}    空值的也会被修改
echo ${var1?aaaa}   没有定义变量值的会被修改
echo ${var2?aaaa}   定义过的不会被修改
echo ${var3?aaaa}   空值的也会被修改
echo ${var1?=aaaa}    没有定义变量值的会被修改
echo ${var2?=aaaa}    定义过的不会被修改
echo ${var3?=aaaa}    空值的也会被修改

5.i++和++i

对变量的影响

i=1
let i++
echo $i
  2
j=1
let ++j
echo $j
  2
对变量几乎没影响,输出都一样

对表达式的值的影响

unset i
unset j
i=1
j=1
let x=i++   先赋值,在运算   在这里x=,y= 就是表达式
let y=++j   先运算在赋值
echo $i   输出2
echo $j   输出2
echo $x   输出1
echo $y   输出2
i++和++i最大的区别在于就是i++是将变量i的值直接赋给新变量名在进行运算而++i是先运算,将运算结果直接赋给新变量名

6.shell中的特殊符号

() 子shell执行例如(ls)

((1>2)) 数值比较,运算

$() 命令替换

$(()) 整数运算

{} 集合,例如touch file{1…2}


${} 变量引用

[] 条件测试,例如[ -d /home -a -f /etc/profile ]

[[]] 条件测试,支持正则=~ 例如 [ [ -d /home && -f /etc/profile ] ]


$[] 整数运算

执行脚本:

./01.sh 需要执行权限在子shell中执行

bash 01.sh 不需要执行权限在子shell中执行

. 01.sh 在当前shell执行,不需要执行权限

source 01.sh 在当前shell执行,不需要执行权限


调试脚本:

sh -n 02.sh 仅调试syntax error

sh -vx 02.sh 以调试的方式执行,查询整个执行过程

ho $j 输出2

echo $x 输出1

echo $y 输出2

i++和++i最大的区别在于就是i++是将变量i的值直接赋给新变量名在进行运算而++i是先运算,将运算结果直接赋给新变量名


目录
相关文章
|
1月前
|
Shell
一个用于添加/删除定时任务的shell脚本
一个用于添加/删除定时任务的shell脚本
75 1
|
18天前
|
Shell Linux 测试技术
6种方法打造出色的Shell脚本
6种方法打造出色的Shell脚本
42 2
6种方法打造出色的Shell脚本
|
4天前
|
XML JSON 监控
Shell脚本要点和难点以及具体应用和优缺点介绍
Shell脚本在系统管理和自动化任务中扮演着重要角色。尽管存在调试困难、可读性差等问题,但其简洁高效、易于学习和强大的功能使其在许多场景中不可或缺。通过掌握Shell脚本的基本语法、常用命令和函数,并了解其优缺点,开发者可以编写出高效的脚本来完成各种任务,提高工作效率。希望本文能为您在Shell脚本编写和应用中提供有价值的参考和指导。
14 1
|
9天前
|
Ubuntu Shell 开发工具
ubuntu/debian shell 脚本自动配置 gitea git 仓库
这是一个自动配置 Gitea Git 仓库的 Shell 脚本,支持 Ubuntu 20+ 和 Debian 12+ 系统。脚本会创建必要的目录、下载并安装 Gitea,创建 Gitea 用户和服务,确保 Gitea 在系统启动时自动运行。用户可以选择从官方或小绿叶技术博客下载安装包。
23 2
|
23天前
|
监控 网络协议 Shell
ip和ip网段攻击拦截系统-绿叶结界防火墙系统shell脚本
这是一个名为“小绿叶技术博客扫段攻击拦截系统”的Bash脚本,用于监控和拦截TCP攻击。通过抓取网络数据包监控可疑IP,并利用iptables和firewalld防火墙规则对这些IP进行拦截。同时,该系统能够查询数据库中的白名单,确保合法IP不受影响。此外,它还具备日志记录功能,以便于后续分析和审计。
43 6
|
19天前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
1月前
|
监控 Unix Shell
shell脚本编程学习
【10月更文挑战第1天】shell脚本编程
66 12
|
1月前
|
存储 运维 监控
自动化运维:使用Shell脚本简化日常任务
【9月更文挑战第35天】在IT运维的日常工作中,重复性的任务往往消耗大量的时间。本文将介绍如何通过编写简单的Shell脚本来自动化这些日常任务,从而提升效率。我们将一起探索Shell脚本的基础语法,并通过实际案例展示如何应用这些知识来创建有用的自动化工具。无论你是新手还是有一定经验的运维人员,这篇文章都会为你提供新的视角和技巧,让你的工作更加轻松。
51 2
|
1月前
|
存储 Java Shell
Shell 变量
10月更文挑战第2天
24 0
|
1月前
|
存储 Shell Linux
【Linux】shell基础,shell脚本
Shell脚本是Linux系统管理和自动化任务的重要工具,掌握其基础及进阶用法能显著提升工作效率。从简单的命令序列到复杂的逻辑控制和功能封装,Shell脚本展现了强大的灵活性和实用性。不断实践和探索,将使您更加熟练地运用Shell脚本解决各种实际问题
25 0