shell脚本中的变量

关于Linux操作系统中当前shell进程与子shell进程的详细解释

如上图所示,使用ps -f可以当前查看Linux操作系统中当前正在运行的进程。

然后敲bash后,相当于在当前的bash shell环境下又创建了一个子bash shell的进程,

如上图所示,后来创建的bash shell的PPID是前一个bash shell的PID

使用./hello.sh的方式去调用脚本就相当于是在原来bash shell的基础上又开了一个子bash shell,然后在子bash shell中去调用脚本。 

敲exit命令时会发现没有退出Linux操作系统就在于当前是在子shell进程中,

开子shell与不开子shell的区别就在于,环境变量的继承关系,如在子shell中设置的当前变量,父shell中是不可见的。

系统预定义变量

在shell编程中存在系统变量和用户变量,其中系统变量的作用范围是全局,而用户变量的作用范围却是分为全局变量和局部变量。

局部变量是只对当前的bash起效。

Linux操作系统中shell编程的系统变量大部分是全局变量,小部分是局部变量。

$HOME表示当前用户的家目录,$PWD表示当前用户的工作目录,$SHELL表示当前的shell会话,$USER表示当前的用户,

如果想查看当前所有的全局环境变量的话,就是用env,printenv的功能和普通的env大致是一样的。

如果想使用系统变量,就使用echo或者printenv加系统变量。

如上图所示,如果只是想查看当前系统变量的值的话,加不加$符无所谓但是如果想使用系统变量的值的话,就必须加上$了。

在Linux操作系统中可以使用set命令可以用来显示当前所有的shell变量(包括环境变量)及其值。

用户的自定义变量

如上图所示,在Linux操作系统中shell编程语言中关于用户变量的定义只需要变量名=变量值,就可以直接定义变量,不需要像其他编程语言一样去定义变量的类型再去给变量赋值,如果变量值中有空格就需要我们将将变量值用引号引起来才能生效,这时定义的变量属于用户变量中的局部变量,即在原来的bash环境中有,在子bash中没有,

可以使用set | grep my_var这样的命令来查找用户创建的变量的值,

如上图所示,在新创建的子bash中,echo $my_var发现不输出变量的值,这就说明用户创建的my_var是一个局部变量。

如上图所示,在子bash中找不到用户创建的变量的值,但是退出子bash后,可以查找到用户创建的变量的值,说明这时一个用户变量中的局部变量,如果像把局部变量定义成全局变量的话,如下图操作。

如上图所示,如果我们想定义一个全局变量它的作用范围是在-bash以及嵌套的bash中有效,

这就需要使用export 变量名称,来将用户创建的局部变量定义为一个全局变量,这时再创建一个bash环境,进入到这个子bash环境时,echo 变量名称,发现变量的值就可以输出打印了。

如果在子bash中对这个变量进行变量值的修改时,再进入到别的bash环境中,就发现原来变量的值并没有改变,

所以对这个全局变量的修改只在修改界面中的bash中有效,在其他的bash环境中对变量的修改操作无效。当然如果在子bash中对变量进行更改后,使用export 变量名称,这时子bash包括它嵌套的子bash中修改的变量值都是可以看到的。

如上图所示,在子bash中对全局变量进行数值修改以后,再将变量重新定义为全局变量时,切换到-bash环境中依然看不到对变量的修改操作,所以在子bash中对变量进行更改后,使用export 变量名称,这时子bash包括它嵌套的子bash中修改的变量值都是可以看到的。但是在子bash以外的bash环境中看不到对变量的修改操作。

在不同bash环境中对脚本的调用

如上图所示,在脚本hello.sh中加上了一个变量,当调用这个脚本的时候,就可以打印输出这个变量的值,而随着调用脚本的bash环境不同,其调用脚本的结果也不同,当使用source 调用脚本的时候,bash环境是当前的bash环境,而使用./hello.sh来调用脚本的时候,bash环境就是当前bash环境的子bash环境,

这时定义一个用户变量中的局部变量,然后在脚本hello.sh中添加这个变量,发现在当前bash环境中的子bash环境中这个局部变量是不生效的。而如果以. hello.sh或者source hello.sh来在当前bash环境中调用这个脚本局部变量就可以生效。

如果使用export 局部变量名称,这时该局部变量就变成了全局变量,这时再使用./hello.sh(在当前bash环境下启动一个子bash,或者给脚本添加x执行权限,直接通过调用脚本路径的方式来调用脚本)这样的方式来调用脚本,该脚本中的两个变量都生效。

全局变量,只读变量和撤销变量

如上图所示,使用echo 加变量名称,就可以打印变量值,对于shell编程来说,变量名=变量值,这期间没有能对变量值进行运算的操作,如果想对变量值进行运算就需要使用a=$[5+9]或者是a=$((1+5))这样的操作。

这里是关于shell编程的运算符的介绍,

只读变量

这里的意思就是说定义一个常量,此时这个变量中的变量值只能进行读的操作,不能对这个变量值进行修改。

如上图所示,这是在定义一个只读变量,使用readonly 变量名称=变量值,这就是在shell中定义了一个只读变量,如果此时想修改这个变量的变量值,就会被提醒,这是一个只读变量,不能进行对变量值的修改操作。

撤销变量

如上图所示,如果你想撤销一个变量的话,直接unset 变量名,就可以将该变量撤销掉,撤销变量的意义在于该变量没有用处时,撤销掉,节省内存空间。

在shell编程中如果将一个变量定义为一个只读变量,此时直接用unset 变量名称,是不可以撤销这个只读变量的,需要先将这个只读变量的只读状态撤销掉。

如果你确实需要“撤销”这个只读状态,可以采取以下策略之一:

  1. 重新声明变量:你可以在新的Shell作用域中重新声明这个变量,这样就绕过了原来的只读限制。这通常意味着在子shell中或者一个新的脚本进程中来做这件事,因为父shell中的只读属性不会传递给子进程。

     Bash 
    1# 在子shell中重置变量
    2(
    3  myVar="New Value"
    4  echo "$myVar"  # 输出 "New Value"
    5)
    6echo "$myVar"  # 回到父shell,输出仍是 "Hello World"
  2. 使用unset后再重新赋值:注意,unset命令可以删除一个变量,包括只读变量,但这仅在该变量不是全局只读变量时有效。之后,你可以重新声明该变量。但请注意,这实际上是“删除并重新创建”,而非直接撤销只读属性。

     Bash 
    1# 如果变量不是全局只读,可以先unset再赋值
    2unset myVar
    3myVar="New Value"
  3. 避免使用readonly:在设计脚本时,如果预见需要改变变量的值,最初就不要将其声明为只读。

由于Shell中没有直接撤销只读属性的命令,理解和规划你的脚本结构以适应这种限制是很重要的。在大多数情况下,只读变量是用来防止意外修改关键数据的,因此撤销只读状态应当谨慎考虑其必要性。

如何将脚本当作命令一样去使用呢?(前提在不改变/bin/目录内容的前提下.)

如上图所示,可以将脚本的名称cp 复制到/bin/下,此时对于脚本的调用就可以像正常的命令一样,但是/bin/是Linux操作系统储存命令shell脚本的地方,特别不建议对/bin/中的内容进行修改。

如上图所示,可以将脚本的名称复制到/root/bin目录中,这样就可以将该脚本的调用当成像命令一样了,或者直接将脚本的绝对目录加入到/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin中,这样对脚本的调用也可以像命令的调用一样了。

[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]#
 

对于脚本来说,如何给脚本加参数?

对于脚本来说,这个脚本的作用对象不同,给传递给脚本的参数也不相同。

在Linux操作系统中对参数的获取。这里的$数字参数,主要是位置参数。

如上图所示,当你想在调用脚本的时候,给脚本传递相应的参数的话,就需要在脚本中编写的时候,加入相应的变量来储存参数,比如$1这样的变量。

如上图所示,在编写脚本后记得给脚本添加上可执行权限,

script name:可以直接输出此时调用脚本的路径,

1st paramater :$1 这里的$1用来承接变量1

2nd paramater:$2这里的$2用来承接变量2

在Linux操作系统中对参数的获取,这里的$n参数,主要作用是统计系统传给脚本的参数的个数。

如上图所示,parameter numbers:2 表示当前系统传给脚本的参数个数是两个。

在Linux操作系统中对参数的获取,这里的$*和$@参数,$*的主要作用是代表命令行中所有的参数,$*把所有的参数看成是一个整体,$@把每个参数区分对待。

$*获取到的像是一个整体比如abc def

$@获取到的像是一个数组,比如[abc,def]  这里的$@获取到的结果像是一个数组,此时就可以使用循环去遍历里面的参数,

在Linux操作系统中对参数的获取,$?的作用是返回最后一次执行脚本的

$?这个特殊变量用来储存执行命令之后的返回值,如果返回值是0则表示上一条命令执行成功。

如上图所示,当一个命令执行成功的时候,此时敲命令 echo $?系统返回数字0表示命令执行成功,

当一个命令执行失败的时候,此时敲命令echo $?系统返回数字127表示命令执行失败。

注意在shell编程中使用单引号包围字符串和使用双引号包围字符串的时候有什么区别?

在Shell编程中,当你使用单引号(')包围字符串时,Shell会原样输出字符串内的内容,不做任何变量替换或特殊字符处理。所以,如果你写了 echo '======$n======',Shell会将$n视为字符串中的文字字符,而不是一个变量引用。它会原封不动地输出 ======$n=====, 而不会尝试去替换$n为它可能代表的变量值。

如果你想让Shell解析 $n 作为变量,并显示其值(假设之前已定义),你应该使用双引号("):

 

Bash

1echo "======$n======"

在双引号中,Shell会执行变量扩展、命令替换等操作,因此如果之前有定义变量 n,它的值就会被正确地插入到字符串中输出。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录-Day35

134. 加油站 在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 给定两个整数数组 …

使用 AST语法树分析与修改Javascript 代码

1、AST语法树简介 当编写代码分析工具、代码美化工具、网站逆向分析等场景时,通常需要使用AST语法树技术。 比如项目开发过程中常遇到的场景:某个公共函数名需要更改,但被很多文件多处代码调用,手工修改非常容易漏改、改错等&…

微服务开发与实战Day11 - 微服务面试篇

一、分布式事务 1. CAP定理 1998年,加州大学的计算机科学及Eric Brewer提出,分布式系统有三个指标: Consistency(一致性)Availability(可用性)Partition tolerance(分区容错性&am…

网络故障经典案例

一、背景分析 企业的网络经常出现整网卡顿的情况,表现为网页没法打开、微信飞书消息转圈圈、视频加载缓慢 等等问题,但有时候又正常,莫名其妙! 问题一直找不到,检查了网络架构没有任何问题,也找了运营商…

充电学习—6、电量计FuelGauge

电量计功能: 检测电池 计量电量 电量计首要工作: 计算电池的剩余容量、充满时容量、电量百分比 电量百分比 剩余容量 / 充满时容量 * 100% SOC RM / FCC * 100% 典型的一个电池包框架: 包含电芯、电量计IC、保护IC、充放电MOSFET、保险丝…

mysql分析常用锁

这里写自定义目录标题 1.未提交事物,阻塞DDL,继而阻塞所有同表的后续操作,查看未提交事务的进程2.存着正在进行的线程数据。3.根据processlist表中的id杀掉未释放的线程4.查看正在使用的表5.mysql为什么state会有waiting for handler commit6.什么情况导…

如何有效处理独立站遭受的网络攻击

随着电子商务的蓬勃发展,独立站成为了众多商家展示产品、吸引客户的重要平台。然而,这同时也吸引了不法分子的目光,使得独立站成为网络攻击的重灾区。本文将深入探讨独立站可能遭受的各种网络攻击类型,并提供一系列实用且可运行的…

Android开发系列(四)Jetpack Compose之Button

在Jetpack Compose中,Button是一个常用的用户界面组件,用于执行某些操作或触发某些事件。Button控件是可触摸的,并且通常会显示一个文本或图标来表示其功能。 要在Jetpack Compose中创建一个Button,可以使用Button()函数&#xf…

8.12 矢量图层面要素单一符号使用二(仅渲染中心点)

文章目录 前言仅渲染中心点(Centroid fill)QGis设置面符号为仅渲染中心点(Centroid fill)二次开发代码实现仅渲染中心点(Centroid fill) 总结 前言 本章介绍矢量图层线要素单一符号中仅渲染中心点&#xf…

Java每日作业day6.18

ok了家人们今天我们继续学习方法的更多使用,闲话少叙,我们来看今天学了什么 1.重载 在同一个类中,可不可以存在同名的方法?重载:在同一个类中,定义了多个同名的方法,但每个方法具有不同的参数类型或参数个…

SuiNS更新命名标准,增强用户体验

SuiNS将其面向用户的命名标准从 xxx.sui 更新为 xxx,让用户能够以一种适用于Web2和Web3世界的方式来代表自己。通过此更新,用户可以在其选择的名称前使用 ,而不是在名称后添加 .sui。 Sui命名服务于去年推出,旨在使Sui上的地址更…

C++ 63 之 函数模版和普通函数的区别

#include <iostream> #include <string> using namespace std;template<typename T> T myAdd(T a, T b){return a b; }int myAdd2(int a, int b){return a b; }int main() {int a 1;int b 2;char c a; // a的ask码 97// cout << myAdd(a,c) <…

探索C嘎嘎的奇妙世界:第十四关---STL(string的模拟实现)

1. string类的模拟实现 1.1 经典的string类问题 上一关已经对string类进行了简单的介绍&#xff0c;大家只要能够正常使用即可。在面试中&#xff0c;面试官总喜欢让学生自己来模拟实现string类&#xff0c;最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数…

vcruntime140_1.dll文件【安装包】【压缩包】【文件】【下载】

安装程序时有时候出现 类似无法启动程序&#xff0c;缺少vcruntime140_1.dll的提示&#xff0c;我们找到该文件并放到对应目录就可以&#xff1b;获取方法有很多&#xff0c;下面介绍两种&#xff1a;&#xff08;方法二更简便&#xff0c;不过建议两种方法都试试&#xff09; …

首张地下地图!D-Wave 专用量子计算机助力沙特阿美完成地震成像

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨沛贤 深度好文&#xff1a;800字丨3分钟阅读 摘要&#xff1a;过去两年中&#xff0c;沙特阿美研究中心一直在使用总部在加拿大的D-Wave 公司的专用量子计算技术&#xff0c;…

基于DDD的编码实践

分层设计 领域驱动设计&#xff08;Domain-driven design, DDD&#xff09; 作为一种复杂软件系统的应对方案&#xff0c;在设计和编码提供了一种新的解决方式&#xff0c;即领域驱动&#xff0c;要求程序员在设计和编码时从领域专家的角度出发来实现架构/代码&#xff0c;做到…

Canvas->不依赖View的Canvas,创建Canvas绘制Bitmap的某个区域

XML文件 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:o…

【Java】已解决java.lang.ArrayIndexOutOfBoundsException异常

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.lang.ArrayIndexOutOfBoundsException异常 一、问题背景 java.lang.ArrayIndexOutOfBoundsException 是 Java 中一个非常常见的运行时异常&#xff0c;它表明程序试图访问数…

POSIX信号量以及读写者模型/环形队列

POSIX信号量 POSIX信号量和SystemV信号量作用相同&#xff0c;都是用于同步操作&#xff0c;达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步,他的本质是一个计数器,对共享资源进行等待或释放 POSIX信号量的重要概念 1.计数器:信号量维护一个计数器&#xff0c;它…

Leaflet地图实例

ReactTypeScript实例&#xff1a; import React, { useEffect, useRef } from "react"; import * as L from "leaflet"; import "leaflet/dist/leaflet.css";const App: React.FC () > {const mapRef useRef<HTMLDivElement>(null);…