shell的变量和引用

news2024/11/24 1:25:13

文章目录

    • 二、变量和引用
      • 2.1 什么是变量
      • 2.2变量的命名
      • 2.3 变量的类型
        • 2.3.1 根据数据类型分类
        • 2.3.2 根据作用域分类
      • 2.4 变量的定义
      • 2.5 shell中的引用
      • 2.6 变量的运算
    • 练习:

二、变量和引用

在程序设计语言中,变量是一个非常重要的概念。也是初学者在进行Shell程序设计之前必须掌握的一个非常基础的概念。只有理解变量的使用方法,才能设计出良好的程序。本节将介绍Shell中变量的相关知识。

2.1 什么是变量

顾名思义,变量就是程序设计语言中的一个可以变化的量,当然,可以变化的是变量的值。几乎所有的程序设计语言中都有定义变量,并且其涵义也大同小异。从本质上讲,变量就是在程序中保存用户数据的一块内存空间,而变量名就是这块内存空间的地址。

在程序的执行过程中,保存数据的内存空间的内容可能会不断地发生变化,但是,代表内存地址的变量名却保持不变。

2.2变量的命名

在Shell中,变量名可以由字母、数字或者下划线组成,并且只能以字母或者下划线开头。对于变量名的长度,Shell并没有做出明确的规定。因此,用户可以使用任意长度的字符串来作为变量名。但是,为了提高程序的可读性,建议用户使用相对较短的字符串作为变量名。

在一个设计良好的程序中,变量的命名有着非常大的学问。通常情况下,用户应该尽可能选择有明确意义的英文单词作为变量名,尽量避免使用拼音或者毫无意义的字符串作为变量名。这样的话,用户通过变量名就可以了解该变量的作用。

2.3 变量的类型

2.3.1 根据数据类型分类

Shell是一种动态类型语言和弱类型语言,即在Shell中,变量的数据类型毋需显示地声明,变量的数据类型会根据不同的操作有所变化。准确地讲,Shell中的变量是不分数据类型的,统一地按照字符串存储。但是根据变量的上下文环境,允许程序执行一些不同的操作,例如字符串的比较和整数的加减等等。

什么是弱类型语言、强类型语言?
强类型和弱类型主要是站在变量类型处理的角度进行分类的。强类型是指不允许隐式变量类型转换,弱类型则允许隐式类型转换。

  • 强类型语言,当你定义一个变量是某个类型,如果不经过代码显式转换(强制转化)过,它就永远都是这个类型,如果把它当做其他类型来用,就会报错

  • 弱类型语言,你想把这个变量当做什么类型来用,就当做什么类型来用,语言的解析器会自动(隐式)转换。

比如:
C语言定义变量,int+变量名,实则前面的int就是给变量内存划分了等级,int定义整型所以空间里只能存放整型,这就是强类型。php、C#和Python等都是强类型语言。

可以使用declare定义变量的类型:declare attribute variable

:declare命令还可输出所有的变量、函数、整数和已经导出的变量

-p:显示所有变量的值

-i:将变量定义为整数,在之后就可以直接对表达式求值,结果只能是整数。如果求值失败或者不是整数,就设置为0。

-r:将变量声明为只读变量。只读变量不允许修改,也不允许删除。(也可使用readonly定义只读变量)

-a:变量声明为数组变量。但这没有必要,所有变量都不必显示定义就可以用作数组。事实上,在某种意义上,似乎所有变量都是数组,而且赋值给没有下标的变量与赋值给下标为0的数组元素相同。

-f:显示所有自定义函数,包括名称和函数体。

-x:将变量设置成环境变量。可使用+x将变量变成非环境变量

2.3.2 根据作用域分类

根据作用域可将变量分为环境变量(全局变量)和普通变量(局部变量)

  1. 环境变量

    环境变量也可称为全局变量,可以在创建它们的shell及其派生出来的任意子进程shell中使用(su -切换用户会读取新的环境变量),环境变量又可分为自定义环境变量和bash内置的环境变量。

(1)自定义环境变量

一般是指用export内置命令导出的变量,用于定义shell的运行环境,保证shell命令的正确执行。环境变量可以在命令行中设置和创建,但用户退出命令行时这些变量值就会丢失,即该环境变量只在当前shell和子shell中有效。如果希望永久保存环境变量,可以在配置文件中设置。

①用户的环境变量配置(non-login shell)

~/.bash_profile或~/.bashrc

②全局环境变量的配置(login shell)

/etc/bashrc、/etc/profile文件或者/etc/profile.d目录中定义。

注意:按照系统规范,所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前,都应该用命令export导出。

有一些环境变量,比如HOME,PATH,SHELL,UID,USER等,在用户登录前就已经被/bin/login程序设置好了,通常环境变量被定义并保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile中。

(2)bash内置的环境变量

shell内置的环境变量是所有的shell程序都可以使用的变量。shell程序在运行时,都会接收一组变量来确定登录用户名、命令路径、终端类型、登录目录等,这组变量就是环境变量。环境变量会影响到所有的脚本的执行结果。
在这里插入图片描述
:可使用env查看环境变量

2、普通变量

普通变量也可称为局部变量,与全局变量相比,局部变量的使用范围较小,通常仅限于某个程序段访问,例如函数内部。在Shell语言中,可以在函数内部通过local关键字定义局部变量,另外,函数的参数也是局部变量。

示例:全局变量和局部变量的区别:

[root@localhost ~]# vim 6.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"
[root@localhost test]# chmod a+rx var.sh
[root@localhost test]# ./var.sh
global variable v1 is 1
local variable v1 is 2
global variable v1 is 1

2.4 变量的定义

在Shell中,通常情况下用户可以直接使用变量,而毋需先进行定义,当用户第一次使用某个变量名时,实际上就同时定义了这个变量,在变量的作用域内,用户都可以使用该变量。

1、变量定义示例:变量名=变量值

#!/bin/bash
#定义变量a
a=1
#定义变量b
b="hello"
#定义变量c
c="hello world"
#定义备份路径
bak_dir=/data/backup
#把一个命令的结果赋值变量
变量名=`ls`
变量名=$(ls)

注意
(1)“=”前后不能有空格

[root@localhost ~]# a= 3
-bash: 3: 未找到命令
[root@localhost ~]# b =4
-bash: b: 未找到命令

(2)字符串类型建议用引号括起来,尤其是特殊字符或有空格

stu_name="zhang san"	

引用变量:$变量名 或者 ${变量名}
查看变量:echo $变量名,set(可查看所有变量:包括自定义变量和环境变量),env显示全局变量,declare输出所有的变量、函数、整数和已经导出的变量。
取消变量:unset 变量名
作用范围:仅在当前shell中有效

:可使用export指令将变量转换成环境变量

2、位置参数和预定义变量
许多情况下,Shell脚本都需要接收用户的输入,根据用户输入的参数来执行不同的操作。从命令行传递给Shell脚本的参数又称为位置参数,Shell脚本会根据参数的位置使用不同的位置参数变量读取它们的值。

在这里插入图片描述
示例:

[root@localhost test]# vim param.sh
echo "第1个位置参数是$1"
echo "第2个位置参数是$2"
echo "所有参数是: $*"
echo "所有参数是: $@"
echo "参数的个数是: $#"
echo "当前进程的PID是: $$"
[root@localhost test]# bash param.sh shuju1 shuju2
第1个位置参数是shuju1
第2个位置参数是shuju2
所有参数是: shuju1 shuju2
所有参数是: shuju1 shuju2
参数的个数是: 2
当前进程的PID是: 23278

$?的示例:

[root@localhost test]# vim ping.sh
#!/bin/bash
ping -c2 $1 &> /dev/null
if [ $? = 0 ];then
echo "host $1 is ok"
else
echo "host $1 is fail"
fi
[root@localhost test]# chmod a+rx ping.sh
[root@localhost test]# ./ping.sh 192.168.168.128
host 192.168.168.128 is ok

$*(//这个是类似于数组)和 $@(//类似于个体)的区别
示例:

[root@localhost test]# set -- "i have" a cat #利用set命令设置位置参数
[root@localhost test]# echo $#
3
[root@localhost test]# echo $*
i have a cat
[root@localhost test]# echo $@
i have a cat
[root@localhost test]# for i in $*;do echo $i;done
i
have
a
cat
[root@localhost test]# for i in $@;do echo $i; done
i
have
a
cat
[root@localhost test]# for i in "$*";do echo $i;done
i have a cat
[root@localhost test]# for i in "$@";do echo $i;done
i have
a
cat
[root@localhost test]# shift #使用该指令可将位置参数左移一位
[root@localhost test]# echo $1
a
[root@localhost test]# shift
[root@localhost test]# echo $1
cat

2.5 shell中的引用

在bash中有很多特殊字符,这些特殊字符就具有特殊含义。引用就是通知shell将这些特殊字符当作普通字符来处理。
在这里插入图片描述
说明反引号中的字符串将被解释为shell命令

[root@localhost ~]# echo "current_user is: $USER"
current_user is: root
[root@localhost ~]# echo 'current_user is: $USER'
current_user is: $USER
[root@localhost ~]# echo "current_user is: `whoami`"
current_user is: root
[root@localhost ~]# echo 'current_user is: `whoami`'
current_user is: `whoami`

2.6 变量的运算

与其他的程序设计语言一样,shell也有很多运算符。
在这里插入图片描述
在这里插入图片描述
示例:

[root@localhost ~]# r=$((2+5*8))
[root@localhost ~]# echo $r
42
[root@localhost ~]# let r=3+2
[root@localhost ~]# echo $r
5
[root@localhost ~]# r=`expr 4+2`
[root@localhost ~]# echo $r
4+2
[root@localhost ~]# r=`expr 4 + 2`
[root@localhost ~]# echo $r
6
#使用expr计算字符的长度
[root@localhost test4]# char="i have a"
[root@localhost test4]# expr length "$char"
8
[root@localhost ~]# r=$[3+2]
[root@localhost ~]# echo $r
5
[root@localhost ~]# awk 'BEGIN {print 2+3*2}'
8
[root@localhost test4]# echo "6.282 3.14" | awk '{print ($1-$2)}'
3.142
[root@localhost ~]# declare -i r=3+2
[root@localhost ~]# echo $r
5

实验:计算用户输入的任意两个整数的和、差、乘积、商、余数。
方法一:

[root@localhost test4]# cat 1.sh
#!/bin/bash
a=$1
b=$2
echo a+b=$(($a+$b))
echo a-b=$((a-b))
echo a*b=$((a*b))
echo a/b=$((a/b))
echo a%b=$((a%b))
[root@localhost test4]# ./1.sh 10 3
a+b=13
a-b=7
a*b=30
a/b=3
a%b=1

方法二:

[root@localhost test4]# cat 1.1.sh
#!/bin/bash
read -p "please input two number:" a b
echo $a+$b=$(($a+$b))
echo $a-$b=$((a-b))
echo $a*$b=$((a*b))
echo $a/$b=$((a/b))
echo $a%$b=$((a%b))
[root@localhost test4]# ./1.1.sh
please input two number:3 4
3+4=7
3-4=-1
3*4=12
3/4=0
3%4=3

在这里插入图片描述
示例:截取字符串

[root@localhost ~]# str1="hello world"
#返回变量长度
[root@localhost ~]# echo ${#str1}
11
#变量截取
#指定起始位置,一直到结束
[root@localhost ~]# echo ${str1:1}
ello world
#指定长度,不指定起始位置默认从开头开始
[root@localhost ~]# echo ${str1::3}
hel
#指定起始位置和长度
[root@localhost ~]# echo ${str1:1:3}
ell
#从右边第几个字符开始,及字符的个数
[root@localhost ~]# echo ${str1:0-1:1}
d
#输出右边的几个字符
[root@localhost ~]# echo ${str1:0-5}
world
[root@localhost ~]# echo ${str1: -5}
world
#提取完整字符串
[root@localhost ~]# echo ${str1:-5}
hello world

示例:删除字符串

#获取后缀名tar.gz
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename#*.}
[root@localhost ~]# echo $file
tar.gz
#获取后缀名.gz
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename##*.}
[root@localhost ~]# echo $file
gz
#截取testfile.tar
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename%.*}
[root@localhost ~]# echo $file
testfile.tar
#截取testfile
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename%%.*}
[root@localhost ~]# echo $file
testfile

练习:

1.定义两个变量:num1=10和num2=2

使用(()): 计算num1 + num2的值并输出

[root@shell 0130]# num1=10
[root@shell 0130]# num2=2
[root@shell 0130]# echo $((num1+num2))
12

使用let: 计算num1 * num2的值输出

[root@shell 0130]# num1=10
[root@shell 0130]# num2=2
[root@shell 0130]# let num=num1*num2
[root@shell 0130]# echo $num
20

使用expr: 计算num1 对 num2执行或的位运算

[root@shell 0130]# num1=10
[root@shell 0130]# num2=2
[root@shell 0130]# expr $num1 '|' $num2
10

     0000 0010
|    0000 1010
     0000 1010=10

使用$[]: 计算 num2的num1次方值

[root@shell 0130]# num1=10
[root@shell 0130]# num2=2
[root@shell 0130]# num3=num1+num2
[root@shell 0130]# echo $[num3]
12

使用declare: 计算 num1 除以 num2的值

[root@shell 0130]# num1=10
[root@shell 0130]# num2=2
[root@shell 0130]# declare -i num3=num1/num2
[root@shell 0130]# echo $num3
5

使用计算num2除num1的值
• 方法一:使用declare计算

[root@shell 0130]# num1=10
[root@shell 0130]# num2=2
[root@shell 0130]# declare -i num3=num2/num1
[root@shell 0130]# echo $num3
 0

• 方法二:$[]

[root@shell 0130]# num1=10
[root@shell 0130]# num2=2
[root@shell 0130]# num3=num2/num1
[root@shell 0130]# echo $[num3]或者
[root@shell 0130]# echo $[num3=num2/num1]
0

• 方法三:expr

[root@shell 0130]# num1=10
[root@shell 0130]# num2=2
[root@shell 0130]# expr $num2 '/' $num1
 0

• 方法四:let

[root@shell 0130]# num1=10
[root@shell 0130]# num2=2
[root@shell 0130]# let num=num2/num1
[root@shell 0130]# echo $num
 0
  1. path=/data/data1/data2.txt
    • 去获取它所在的目录
    ○ 方法一:使用偏移量提取长度为length的代码片

    [root@shell 0130]]# path=/data/data1/data2.txt
    [root@shell 0130]# echo ${path:0:11}
    /data/data1
    

○ 方法二:从$开头开始删除最长匹配Word子串(从右到左)

	[root@shell 0130]# path=/data/data1/data2.txt
	[root@shell 0130]# echo ${path%/data2.txt}
	/data/data1

○ 方法三:从$结尾开始删除最长匹配Word子串(从右到左)

[root@shell 0130]# path=/data/data1/data2.txt
[root@shell 0130]# echo ${path%%/data2.txt}
 /data/data1

• 去获取文件的名字
○ 方法一:偏移量

[root@shell 0130]# path=/data/data1/data2.txt
[root@shell 0130]# echo ${path:12}
data2.txt

○ 方法二:从$开头开始删除最短匹配Word子串(从左到右)

[root@shell 0130]# path=/data/data1/data2.txt
[root@shell 0130]# echo ${path#/data/data1/}
data2.txt

○ 方法三:从$结尾删除最短匹配Word子串(从左到右)

[root@shell 0130]# path=/data/data1/data2.txt
[root@shell 0130]# echo ${path##/data/data1/}
data2.txt
  1. 设置一个只针对root的环境变量:ENV_ROOT=ROOT
    • 因为是root用户环境变量配置,所以需要进入profile配置目录[root@shell 0130]# vim ~/.bash_profile
    在这里插入图片描述
[root@shell 0130]# vim ~/.bash_profile 
[root@shell 0130]# source ~/.bash_profile 
[root@shell 0130]# echo $ENV_ALL
ROOT

设置一个针对所有用户的环境变量: ENV_ALL=ALL
[root@shell 0130]# vim /etc/profile
在这里插入图片描述

[root@shell 0130]# echo $ENV_ALL
ALL

在root用户下访问:ENV_ROOT和ENV_ALL

[root@shell 0130]# echo $ENV_ROOT 
 ROOT
[root@shell 0130]# echo $ENV_ALL 
 ALL

在普通用户下访问:ENV_ROOT和ENV_ALL

[root@shell 0130]$ echo $ENV_ALL 
 ALL
 
 ROOT用户不能访问,输出结果为空白的行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333979.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计讯物联智慧灯杆网关数字赋能智慧公园,点亮城市新未来

方案背景 …… 公园作为城市景观与生态要素的空间载体,是市民远离尘嚣、缓解压力的理想休闲地。随着人们生活水平的提高,公园的信息化与智能化成为公园建设的必然方向。计讯物联依托于物联网技术,以绿色发展理念为指导,充分考虑…

/proc/cpuinfo详解

在分析该文件输出之前,我们先理解下几个重要的概念:物理CPU、CPU核心数、逻辑CPU。 物理CPU数(physical id):主板上实际插入的cpu数量,不重复的 physical id 有几个就有多少个物理CPU。 CPU核心数&#xf…

95. 不同的二叉搜索树 II

95. 不同的二叉搜索树 II题目算法设计:深度优先搜索题目 传送门:https://leetcode.cn/problems/unique-binary-search-trees-ii/ 算法设计:深度优先搜索 二叉树子问题分解 根节点 左右子树的子问题。 根节点的子问题:循环历遍…

高压放大器由哪些部分组成?如何验证它性能的好坏?

虽然很多电子工程师经常使用高压放大器,但是对于高压功率放大器的组成和使用都不太清楚,下面由安泰测试给大家介绍高压放大器的组成部分以及如何验证功率放大器的性能好坏。 一、高压放大器的介绍 高压放大器是一种理想的功率放大器,可以放…

企业版快速开发框架源码 Spring Cloud快速开发脚手架源码

一款 Java 语言基于Spring Cloud Alibaba、SpringBoot、Mybatis、Seata、Sentinel、RabbitMQ、FastDFS/MinIO、SkyWalking等主要框架和中间件,精心打造的一款模块化、插件化、高性能的快速开发框架,可用于快速搭建后台管理系统。 私信了解更多&#xff…

(九)docker复杂安装-安装mysql主从复制

目录 前提: 一、新建主服务器容器实例3307 二、进入/mydata/mysql-master/conf目录下新建my.cnf 三、修改完配置后重启master实例 四、进入mysql-master容器并测试 五、master容器实例内创建数据同步用户 六、新建从服务器容器实例3308 七、进入/mydata/mys…

提取接近竖直物体(粗定位)

由于项目的需要提取图像之中的一个接近于竖直的物体,一般的方法是进行图像分割,分割方式使用什么OTSU方式以及hsv方法等等。但是项目中使用的相机是黑白相机,会受到一定的限制。因此想到的是使用线条提取方式。线条提取方式之中最好的方法是使…

102-并发编程详解(中篇)

这里续写上一章博客 Phaser新特性 : 特性1:动态调整线程个数 CyclicBarrier 所要同步的线程个数是在构造方法中指定的,之后不能更改,而 Phaser 可以在运行期间动态地 调整要同步的线程个数,Phaser 提供了下面这些方…

Quantum 构建工具使用新的 TTP 投递 Agent Tesla

Zscaler 的研究人员发现暗网上正在出售名为 Quantum Builder 的构建工具,该工具可以投递 .NET 远控木马 Agent Tesla。与过去的攻击行动相比,本次攻击转向使用 LNK 文件。 Quantum Builder 能够创建恶意文件,如 LNK、HTA 与 PowerShell&…

clickhouse集群安装

单机安装 yum install yum-utilsrpm --import https://repo.clickhouse.com/CLICKHOUSE-KEY.GPGyum-config-manager --add-repo https://repo.clickhouse.com/rpm/clickhouse.reposudo yum install clickhouse-server clickhouse-client 配置文件 vim /etc/clickhouse-serve…

FFmpeg集成qsv的编译安装

文章目录FFmpeg集成qsv的编译安装一、参考二、编译安装流程1. LibVA 和 Media-Driver 的安装2. Intel Media SDK 编译3. ffmpeg的编译安装4. 验证安装FFmpeg集成qsv的编译安装 一、参考 Ubuntu20.04 ffmpeg添加 Intel核显QSV加速支持 视频和视频帧:Intel GPU&…

SpringCloud保姆级搭建教程四---Gateway

1、gateway干嘛用的呢? 答,系统保安,所有想访问系统的请求都要通过gateway2、来吧,开始吧。第一步,创建个模块,就叫gateway。创建模块的步骤,前面都贴过图哦3、添加依赖,在gateway模…

SSRF漏洞 | iwebsec

文章目录SSRF漏洞介绍00-SSRF漏洞验证01-SSRF漏洞文件读取02-SSRF漏洞内网探测03-SSRF漏洞内网应用攻击源码分析SSRF漏洞介绍 这篇文章写地很好。 SSRF(Sever-Side-Request-Forgery,服务端请求伪造)是一种由攻击者构造请求,由服…

【逐步剖C】-第六章-结构体初阶

一、结构体的声明 1. 结构体的基本概念 结构体是一些值的集合,这些值称为成员变量。结构体的每个成员可以是不同类型的变量。结构体使得C语言有能力描述复杂类型。 如学生,有姓名、学号、性别等;如书,有作者,出版日期…

LeetCode-(94,144,145).二叉树的前中后续遍历

目录二叉树的前序遍历二叉树的中序遍历二叉树的后序遍历二叉树的前序遍历 递归 class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> list new ArrayList<>();dfs(root,list);return list;}public static void dfs(T…

C# JSON的使用实例和jsonNet程序包的安装

建一个txt文档&#xff0c;存放json内容[{"id":2,"name":"净化","damage":0},{"id":4,"name":"隐身","damage":10000},{"id":6,"name":"疾跑","damage&q…

出现failed to load steamui.dll如何解决?好的修复方法推荐

当你电脑突然出现failed to load steamui.dll的时候&#xff0c;你是否一脸懵逼&#xff1f;根本不知道发生啥时候&#xff0c;突然就会这样报错&#xff0c;其实造成这个原因&#xff0c;主要是因为问题出在steam上&#xff0c;我们还是有很多种方法可以解决的&#xff0c;今天…

OpenCV基础知识与基本操作

1 基本语法操作 1 读取图像 读取图像的如法如下 img cv2.imread(图像地址[,flags])cv2暂不支持读取中文路径&#xff0c;所以务必确认地址中不含中文。 flags为选填项&#xff0c;可以设置读取图片时的处理方式: cv2.IMREAD_UNCHANGED&#xff1a;-1&#xff0c;读入图像并…

一天一道力扣题

300. 最长递增子序列给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列…

es-04搜索和查询

文章目录搜索和查询查询的上下文查询语法1.Searchtimeout&#xff1a;2.ES常用查询&#xff1a;(1)Query_string&#xff1a;(2)Query DSL&#xff1a;(3)Full-text queries&#xff1a;全文检索(5)Query and filter&#xff1a;查询和过滤Deep paging图解Scroll search&#x…