编程基础 - 变量与常量
编程基础 - 变量与常量
返回序言及专栏目录
文章目录
- 编程基础 - 变量与常量
- 前言
- 一、变量是什么?
- 二、为什么要有变量
- 三、局部变量和全局变量
- 四、常量
- 五、只读变量
- 小结
前言
变量是编程最重要知识点之一,从根本上讲,编程就是对数据的操作,让数据按我们设定的逻辑进行运算。变量是用于存储数据的内存地址的人性化表示方式。在shell中,数据类型比较简单,它属于弱数据类型的编程语言,简而言之它自动帮你处理了有关数据类型的工作。
一、变量是什么?
顾名思义,变量就是可以变化的量。很多书上这么写的,笔者也学习一下,但这是一句没什么意义的话,纯粹是为了让人更迷糊的说法。
变量是内存地址的别名,别名就是外号的文雅说法。这是某本知名C/C++语言著作上的说法(具体是哪本书我忘记了),当然外号这句是笔者加的,从这个角度比较容易解释什么是变量。
都知道计算机系统中内存是必不可少的,数据是暂时存储在内存当中的。所以当你用PS修图的时候,如果没有保存就突然停电,来电以后你就要找出原图重新开始修1。这就是因为内存中的数据没有被保存到我们的硬盘上。
既然数据是先存储在内存中的,不管内存有多大,把内存细分成字节来管理(1G内存约有1千兆个字节,兆表示10的6次方)。这个数量是极其庞大的,大到我们光用二进制写一个内存地址就要写很久,程序在退休前肯定写不完,还得找个继承人接着写!更关键的是你无法记住这么长的一串数字表示的地址。所以我们要有一个好记的简短的名字来给我们所使用到的内存地址命名。
当然实际情况肯定是比这复杂多了,内存实际是由系统管理的,系统分配给你哪块就用哪块。变量只是给这部分内存起了一个名字。希望这么解释变量能让读者有个概念,变量不是什么稀奇的玩意,就是一个内存地址的名字。
那为什么那么多书都说变量是可以变化的量呢?那些作者比笔者我傻吗?肯定不是的,看下一节的演示你就明白,为什么说它是可以变化的量了。
二、为什么要有变量
对啊,我不用变量不就行了?要这种抽象的概念来做什么呢?假设我们要求计算机计算1+2等于多少,不用变量你输入echo $((1+2))
,计算机也会告诉你是3,没毛病。那我们要学习高斯同学的1加到100呢?你把1到100都写一遍吗?显然没有这个必要,加数是有规律的,每次加1,那么我们可以在变量被使用后,每次让它加上1,就是下一次计算的加数了。计算出的和也是一个道理,先让和是1+2的结果,下一次计算,我们让和加上3,以此类推,就轻松的得出结果了。当然这个高斯同学小学时的例子太简单,我们来个复杂点的著名例子:
有数列1,1,2,3,5,8,13 … 我们想知道第37个数是什么,之所以要37个是怕读者太聪明,口算得出结果~ 显然它的规律是:每个数都是前两个数的和。我们可以编写程序来计算:
#!/bin/sh
a=1
b=1
i=3
while [ $i -lt 38 ]dotmp=$aa=$bb=$tmp+$bi=$i+1done
echo $b
我就不信有口算这么厉害的人,没算出来吧~ 我们看看具体逻辑细节:
- while是一个循环,只要当变量
i
小于38,它就一直在do
和done
之间循环。 - 每次循环程序会把变量
a
的值赋值给变量tmp
(用于记录变量a的值,下行a的值会改变)。 - 再把变量
b
的值给变量a,把变量tmp
和b
的值加起来给b。 - 用变量
i
加上1表示计算了一次,直到变量i
等于37,while循环条件不满足了,程序跳出循环。echo
显示结果
这个程序的4个变量在运行时不停的改变自身存储的值。正是因为变量的值在程序的运算过程中不停的变化,我们才叫它变量!变量的存在才让程序变得简洁、灵活。
三、局部变量和全局变量
通常,我们将变量分为局部变量和全局变量。在函数内部被定义的变量,我们叫它局部变量,它只在函数内部作用。当函数被调用结束时,这个变量也就销毁了。相对的在函数外部定义的变量,我们称之为全局变量,这种变量在整个程序运行期间起作用。
这里引出了函数和调用的概念,函数我们可以认为是一个功能模块,它是为了实现某一个功能而定义的代码集合。局部变量只在定义它的函数内部有效,这个函数就是它的作用域。
如果局部变量和全局变量重名,全局变量会在同名局部变量的函数内被屏蔽。因为全局和局部是个相对的概念,相对于整个系统来说,每个程序内定义的变量都是局部变量。
这么分是有意义的:主要是为了节省内存空间的占用,局部变量用完就销毁的特性避免内存被无意义的数据填满。同时也能让程序员不用关心程序的其它部分定义了什么变量,不然多个程序员协作,大家就天天为了变量命名权打架了。
通常程序员会把全局变量写在程序的开始部分,这个开始并不一定是程序代码的最上部,而是指程序执行的入口部分,很多时候这个入口都写在程序的最下面部分。当然写在代码最前面也是一种好习惯。这么做是为了阅读程序方便,实际上只要变量在被使用前定义就行。
大多数编程语言规定,变量名只能用大小写字母和数字、下划线_ 组成,且数字不能位于变量名开头。
我们用几个例子来看一下:
age=23 # 很好的变量名,简单又有意义
age_1=24 # 较好的变量名,还可以命名多个类似的
_age_=23 # 通常程序员喜欢用下划线在前的变量表示在内部调用的
_tmp=23 # 也有程序员喜欢用这种变量名表示临时的
years_old=23 # 有很多程序员喜欢这样命名,也常用于函数命名
yearsOld=23 # 这叫驼峰命名,也是很常用的,也是通常用于函数名
AGE=23 # 符合规则,但通常不用全大写定义变量
abc=23 # 符合规则,但没有意义,不建议使用
1a=23 # 错误的命名方式
四、常量
既然有变量,相应的就有常量。变量是可以变化的量,常量就是通常不变的量。比如Linux系统本身就定义了一些常量:
echo $HOME # 家目录,和~的作用一样
/root
echo $PWD
/tmp/home/root
echo $PATH
/koolshare/bin:/koolshare/scripts:/opt/bin:/opt/sbin:/bin:/usr/bin:/sbin:/usr/sbin:/home/admin:/mmc/sbin:/mmc/bin:/mmc/usr/sbin:/mmc/usr/bin:/opt/sbin:/opt/bin:/opt/usr/sbin:/opt/usr/bin
echo $SHELL
/bin/sh
echo $IFS# 这里有一个空格
echo $USER
admin
echo $UID
0 # 路由器上这个命令可能没有显示
echo $HOSTNAME
RT-AC68U-F2A7
以下是一些常用的系统已定义常量:
- HOME 家目录,和
~
的作用一样 - PWD 当前路径
- PATH 环境常量,可执行程序的搜索路径
- SHELL shell所在路径
- IFS 分隔符,默认为空格,可以用于把字符串按IFS分割成数组
- USER 当前用户名
- UID 当前用户的ID,相应的就有GID,没加入组就没有
- HOSTNME 主机名
我们在程序中也可以自定义常量,它和变量没有本质的区别。命名规则也是一样,只是通常用全大写来命名。这只是一个概念,表示这是个常量,我们不是不能修改它的值,只是不想修改它。包括系统定义的常量,我们也是可以修改的,最常见之一就是IFS:
admin@RT-AC68U-F2A7:/tmp# touch test.txt
admin@RT-AC68U-F2A7:/tmp# echo "this is a test!" > test.txt
admin@RT-AC68U-F2A7:/tmp# cat test.txt
this is a test!
admin@RT-AC68U-F2A7:/tmp# for i in $(cat test.txt)
> do
> echo $i
> done
this
is
a
test!
上述代码中touch
是一个新建空白文件命令,如果要建立的文件已经存在,命令会改变这个文件的最后访问时间记录,并不会改变文件内容。>
重定向符,用于将标准输出(stdout)重定向到文件中。如果目标文件不存在则创建新文件;若已经存在同名文件,会被覆盖。最上面的touch
是可以不写的,只是作者的习惯。
我们把这个字符串改一改再来测试:
admin@RT-AC68U-F2A7:/tmp# echo "this,is,a,test!" > test.txt
admin@RT-AC68U-F2A7:/tmp# cat test.txt
this,is,a,test!
admin@RT-AC68U-F2A7:/tmp# for i in $(cat test.txt)
> do
> echo $i
> done
this,is,a,test!
上面这个例子,很好的说明了IFS的作用,默认以空格来分割字符串,当我们的字符串改成以逗号分隔时,因为字符串中没有空格,所以不进行分割了。下面我们就修改这个IFS常量:
admin@RT-AC68U-F2A7:/tmp# cat test.txt
this,is,a,test!
admin@RT-AC68U-F2A7:/tmp# IFS_OLD=$IFS
admin@RT-AC68U-F2A7:/tmp# IFS=","
admin@RT-AC68U-F2A7:/tmp# for i in $(cat test.txt)
> do
> echo $i
> done
this
is
a
test!
admin@RT-AC68U-F2A7:/tmp# IFS=$IFS_OLD
这个例子说明了,常量是可以修改的,即使它是系统定义的常量。通常我们修改了IFS后要第一时间给改回去。所以程序第一步就是将原IFS值先保存在IFS_OLD中,最后又改回去了。
五、只读变量
如果我们实在不想一个变量或常量被无意中修改,在c/c++中有静态变量的概念,shell中也有只读变量可以做到。你可以定义一个通常不能改变的变量:
admin@RT-AC68U-F2A7:/tmp/home/root# readonly age=23
admin@RT-AC68U-F2A7:/tmp/home/root# echo $age
23
admin@RT-AC68U-F2A7:/tmp/home/root# age=24
-sh: age: is read only
admin@RT-AC68U-F2A7:/tmp/home/root# unset age
admin@RT-AC68U-F2A7:/tmp/home/root# echo $age
23
admin@RT-AC68U-F2A7:/tmp/home/root# unset -v age
admin@RT-AC68U-F2A7:/tmp/home/root# unset age
admin@RT-AC68U-F2A7:/tmp/home/root# echo $age
23
unset
用于删除一个变量。这样定义的变量是只读的,一般情况不能修改,在shell中还设计成很难修改,删除都不能。当然它只在内存中,你重启系统就没了。有人说服务器让你随便重启吗?对的,所以少用这个定义变量的方法。还有人说用unset -v 变量名
可以解除只读属性,至少在路由的这个2.6版内核中是不可行的,这真是够顽强的。笔者也没在多个发行版Linux中测试过这个,估计在ubuntu20.4中是不可行的,笔者查过这个命令的帮助文件:
sal@sal-laptop:~$ uname -a
Linux sal-laptop 5.4.0-169-generic #187-Ubuntu SMP Thu Nov 23 14:52:28 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
sal@sal-laptop:~$ unset --help
unset: unset [-f] [-v] [-n] [名称 ...]取消设定 shell 变量和函数的值和属性。对每一个 NAME 名称,删除对应的变量或函数。选项:-f 将每个 NAME 视为函数-v 将每个 NAME 视为变量-n 将每个 NAME 视为名称引用,只取消其本身而非其指向的变量不带选项时,unset 首先尝试取消设定一个变量,如果失败,再尝试取消设定一个函数。某些变量不可以被取消设定;参见 `readonly'。退出状态:返回成功,除非使用了无效的选项或者 NAME 名称为只读。
从这个帮助文件可以看出,函数也是用unset
来删除的,所以函数和变量是有共通之处的。从本质上讲,变量和函数都是用户在内存中存储的一串0和1。
小结
本章介绍了变量和常量的概念,需要了解变量和常量的命名规则以及通常用法,这个规则在绝大多数的编程语言中是通用的。
返回专栏目录 <<<
某些软件设计了随时保存临时文件的功能,在我们使用软件的过程中定时或检测到活动就保存到硬盘上的一个文件中。当停电后重启电脑,可能可以找到一个临时文件来恢复大部分数据。 ↩︎
相关文章:
编程基础 - 变量与常量
编程基础 - 变量与常量 返回序言及专栏目录 文章目录 编程基础 - 变量与常量前言一、变量是什么?二、为什么要有变量三、局部变量和全局变量四、常量五、只读变量小结 前言 变量是编程最重要知识点之一,从根本上讲,编程就是对数据的操作&a…...
Linux入门攻坚——12、Linux网络属性配置相关知识2
CentOS 7网络属性配置: 传统命名机制:以太网eth[0,1,2,...],wlan[0,1,2...] 可预测功能的命名机制: udev支持多种不同的命名方案: Firmware ,拓扑结构 在对待设备文件这块,Linux改…...
如何自己实现一个分布式事务
实现分布式事务是一个复杂的过程,它需要精心设计并考虑数据的一致性、系统的可用性和分区容错能力。分布式事务确保在分布式系统中,即使是跨多个数据库、服务或消息队列,事务要么完全成功,要么完全失败。 以下是实现分布式事务的…...
使用Nonebot编写QQ机器人
使用 NoneBot 这个工具,来编写 QQ 机器人。 安装基础软件 一、安装 NoneBot 库 直接使用 pip 安装即可 pip install nonebot二、安装酷Q 软件和 HTTP API 插件 酷Q 软件可以直接到官网下载,https://cqp.cc/b/news,或者可以到网盘下载&am…...
认识SpringBoot中的条件注解
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏&…...
使用PAI-DSW搭建基于LangChain的检索知识库问答机器人
教程简述 在本教程中,您将学习如何在阿里云交互式建模(PAI-DSW)中,基于LangChain的检索知识库实现知识问答。旨在建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。 LangChain是一个开源的框架,…...
优雅的通过Shell脚本生成Go的程序包
前言 随着Go语言的普及,越来越多的开发人员选择使用Go编写代码。虽然越来越多的公司项目已使用持续集成/持续部署(CI/CD)工具,用于自动化构建、测试和部署Go程序包,但存在一些部署在ECS服务器的Go程序包或需要手动编译…...
益生菌抗癌?补充这种益生菌,抑制肝癌,还改善肠道健康
撰文 | 宋文法 肠道菌群,是人体不可分割的组成部分,生活在我们肠道内的数万亿细菌对健康起着重要作用,它们影响着人的新陈代谢、消化能力、抵御感染、控制人体对药物的反应,甚至还能预防某些癌症。 非酒精性脂肪肝病,是…...
LLM漫谈(二)| QAnything支持任意格式文件或数据库的本地知识库问答系统
一、QAnything介绍 QAnything (Question and Answer based on Anything) 是致力于支持任意格式文件或数据库的本地知识库问答系统,可断网安装使用。 您的任何格式的本地文件都可以往里扔,即可获得准确、快速、靠谱的问答体验。 目前已支持格式: PDF&…...
Linux环境vscode clang-format格式化:vscode clang format command is not available亲测有效!
问题现象 vscode安装了clang-format插件,但是使用就报错 问题原因 设置中配置的clang-format插件工具路径不正确。 解决方案-亲测有效! 确认本地安装了clang-format工具:终端输入clang-format(也可能是clang-format-13等版本…...
Vue3前端 响应式数据 知识点
一、ref(基本类型数据,也可以定义对象类型的响应式数据。此时底层用的还是reactive) ref 创建基本类型的响应式数据 作用:定义响应式变量语法: let xxx ref(初始值)返回值: 一个 RefImp1 的实例对象,简称 ref对象或ref,ref 对象的 value 属…...
golang数据库连接池设置多少比较合适,如何设置?
设置数据库连接池的大小需要综合考虑应用程序的需求、数据库系统的性能、服务器资源等因素。连接池大小的不合理设置可能导致性能问题或资源浪费。 以下是一些建议: 考虑应用程序的并发需求: 连接池的大小应该足够满足应用程序的并发需求。如果你的应用…...
一、Mybatis 简介
本章概要 简介持久层框架对比快速入门(基于Mybatis3方式) 1.1 简介 https://mybatis.org/mybatis-3/zh/index.html MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投G…...
苹果Vision Pro将于1月27日上市!
在无数期待中,苹果全新产品Vision Pro头显终于定下上市日期。 彭博社记者马克古曼(Mark Gurman)于近日在X(前推特)平台爆料了这一信息,预计苹果Vision Pro头显将于2024年1月27日率先在美国上市。 在过去看…...
密码学(一)
文章目录 前言一、Cryptographic Primitives二、Cryptographic Keys2.1 Symmetric key cryptography2.2 asymmetric key cryptography 三、Confidentiality3.1 Symmetric key encryption algorithms3.2 asymmetric key block ciphers3.3 其他 四、Integrity4.1 secure hashing …...
VueRouter
1、用户权限问题 可以在路由全局前置守卫判断当前vuex里是否有token 有token值证明刚才登录过, 无token值证明未登录 router.beforeEach((to, from, next) > {const token store.state.tokenif (token) {// 如果有token, 证明已登录if (!store.state.userInfo.username) {/…...
什么是React.FC | 封装ant design弹框组件之:ant design 修改密码弹框组件
文章目录 一、什么是React.FC组件的 props 是什么意思二、封装ant design弹框组件之:ant design 修改密码弹框组件定义修改密码弹框组件使用修改密码弹框组件:[重要]关于提交时候,不同组件 表单数据共享报错:Button cannot be used as a JSX component.一、什么是React.FC …...
DHCP
一、DHCP 1.1 什么是dhcp DHCP动态主机配置协议,通常被应用在大型的局域网络环境中,主要作用是集中地管理、分配IP地址,使网络环境中的主机动态的获得IP地址、DNS服务器地址等信息,并能够提升地址的使用率。 DHCP作为用应用层协…...
VS code的使用介绍
VS code的使用介绍 简介下载和安装常用的插件使用教程快捷键 集成Git未找到 Git。请安装 Git,或在 "git.path" 设置中配置。操作步骤打开文件夹初始化仓库文件版本控制状态提交文件到git打开git操作栏位 好用的插件ChineseDraw.io Integration实体关系 Gi…...
【蓝桥杯选拔赛真题57】python兔子分胡萝卜 第十四届青少年组蓝桥杯python 选拔赛比赛真题解析
目录 python兔子分胡萝卜 一、题目要求 1、编程实现 2、输入输出...
Spring MVC中JSON数据处理方式!!!
添加json依赖 <!--spring-json依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.0</version></dependency> 注解 RequestBody:作…...
学习JavaEE的日子 阶段回顾
标识符 含义:给类、变量、方法、接口取名字的时候使用到的字符序列 组成:大小写字母 、数字、$、_、中文 注意事项: 不能以数字开头 区分大小写字母 不能使用除了$和_以外的特殊符号 不能使用Java的关键字 考虑到编码问题不要使用中文 关…...
深入理解 Flink(一)Flink 架构设计原理
大数据分布式计算引擎设计实现剖析 MapReduce MapReduce 执行引擎解析 MapReduce 的组件设计实现图 Spark 执行引擎解析 Spark 相比于 RM 的真正优势的地方在哪里:(Simple、Fast、Scalable、Unified) DAG 引擎中间计算结果可以进行内存持…...
Python pip 常用指令
前言 Python的pip是一个强大的包管理工具,它可以帮助我们安装、升级和管理Python的第三方库。以下是一些常用的pip指令。 1. 安装第三方库 使用pip安装Python库非常简单,只需要使用pip install命令,后面跟上库的名字即可。 # 安装virtuale…...
Eureka工作原理详解
摘要:本文将详细介绍Eureka的工作原理,包括服务注册、服务发现、心跳检测等关键概念。通过阅读本文,您将了解到Eureka如何实现高可用、可扩展的服务注册中心。 一、引言 在微服务架构中,服务注册与发现是一个重要的环节。为了实…...
开源加解密库之GmSSL
一、简介 GmSSL是由北京大学自主开发的国产商用密码开源库,实现了对国密算法、标准和安全通信协议的全面功能覆盖,支持包括移动端在内的主流操作系统和处理器,支持密码钥匙、密码卡等典型国产密码硬件,提供功能丰富的命令行工具及…...
小程序分销商城,打造高效线上购物体验
小程序商城系统,为您带来前所未有的在线购物体验。它不仅提供线上商城购物、在线下单、支付及配送等功能,还凭借其便捷性成为众多商家的首选。 想象一下,商家可以展示琳琅满目的商品,包括图片、文字描述、价格及库存等详尽信息。而…...
Selenium-java 定位元素时切换iFrame时的方法
具体方法如下图所示,如果iFrame中嵌套多层iFrame需要逐层定位到需要的那一层iFrame,完成操作后,执行该代码:driver.switchTo() .defaultContent() ; 是返回最顶部的frame...
WinForms中的UI卡死
WinForms中的UI卡死 WinForms中的UI卡死通常是由于长时间运行的操作阻塞了UI线程所导致的。在UI线程上执行的操作,例如数据访问、计算、文件读写等,如果耗时较长,会使得UI界面失去响应,甚至出现卡死的情况。 解决方法 为了避免…...
做外贸网站效果图/最近三天的新闻热点
Percona集群制定的服务器节点如下: node #1 hostname: pzsd01 IP: 10.1.11.14node #2 hostname: pzsd02 IP: 10.1.11.15node #3 hostname: pzsd03 IP: 10.1.11.16*先决条件 *所有节点都是安装了Linux CentOS 6.4 *防火墙关闭 *selinux disabled *安装部署percona和e…...
大连专业网站建设/seo厂商
//检测客户端是否支持cookieerror_reporting(E_ALL ^ E_WARNING ^ E_NOTICE);ini_set(display_error,TRUE);//检测cookie是否已经生效if($_GET[set] ! yes){//设置cookiesetcookie(test,test,time()60);//刷新本页面$url http://;$url . $_SERVER[SERVER_NAME];$url . $_SERVE…...
长沙网站建设qq交流群/上海seo网站推广
Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归、确保参数传递的正确,需要的朋友可以参考下“备忘”的定义 “memoization”(备忘)这个词是由Donald Mic…...
网站建设公司东莞/厦门网站优化公司
华为消费者 BG 软件部总裁王成录近期表示,华为计划今年 12 月面向开发者提供手机版本鸿蒙 2.0 的 Beta 版本,明年一二月份将会开放部分手机用户升级鸿蒙系统,初步升级会验证几个月,之后全面放开升级。那么华为鸿蒙系统适配流程有哪…...
记事本做网站表格/网页优化seo广州
由于重重原因,我取消maven的下载(可能是jar包没有公服镜像)。导致重新打开sts 时发生异常。 在网上寻找到资料,发现需要删除${workspace}\.metadata\.plugins\org.eclipse.e4.workbench\workbench.xmi文件即可。 参考:…...
网站内容专题怎么做/百度上传自己个人简介
在这一小节,我会试着给出Java IO(java.io)包下所有类的概述。更具体地说,我会根据类的用途对类进行分组。这个分组将会使你在未来的工作中,进行类的用途判定时,或者是为某个特定用途选择类时变得更加容易。 输入和输出 – 数据源和…...