首页 > 系统相关 >【Linux入门】shell基础篇——变量与运算

【Linux入门】shell基础篇——变量与运算

时间:2024-08-27 13:22:34浏览次数:16  
标签:脚本 Shell 入门 echo shell 参数 Linux 字符串 变量

文章目录

shell中的变量

概述

Shell 变量是 Shell 编程中用于存储和引用数据的实体。它们可以是简单的文本字符串、数字,或者在某些情况下,甚至是更复杂的数据结构(尽管这通常依赖于特定的 Shell 和其扩展功能)。变量使得 Shell 脚本能够处理动态数据,增强脚本的灵活性和可重用性。

变量的作用

  1. 存储数据和字符串:Shell变量可以存储数字、文本字符串、文件名等各种类型的数据。这些数据可以是用户输入的信息、命令的输出结果,或者是脚本内部需要的临时数据。
  2. 传递参数:在Shell脚本中,可以通过特殊的变量来获取传递给脚本的参数。比如,$1、 2 、 2、 2、@等变量分别表示第一个参数、第二个参数和所有参数的列表。
  3. 控制程序流程:变量在控制程序流程中也起着重要作用。通过设置变量的值,可以控制脚本的分支和循环,实现条件判断和循环操作。
  4. 提高可读性和可维护性:使用变量可以使脚本更具可读性和可维护性。通过给数据和字符串起一个有意义的名字,可以使脚本更易于理解和修改。
  5. 避免重复输入:使用变量可以避免在脚本中重复输入相同的值或字符串,提高了代码的复用性和效率。

Shell 变量名与变量值

变量名

使用固定的名称,由系统预设或用户定义

  • 规则:
    1. 不要使用系统的命令作为变量名
    2. 不要使用中文
    3. 不能特殊符号开头 可以用_来开头
    4. 在指定变量名的时候有一个默认的规则:计算机:computer 学生:student a= b=
    5. 要有注释,还要注意前后一致
    6. 只能包含字母、数字、下划线
    7. 严格区分大小写
变量值

能够根据用户设置、系统环境的变化而变化

  1. 字符串(String)
    Shell脚本中的变量默认就是字符串。当你给变量赋值时,无论值是什么,它都被视为字符串。
  2. 整数(Int)
    虽然变量本身是字符串,但你可以使用Shell的算术扩展($((expression)))来进行整数运算。算术扩展允许你执行加、减、乘、除等整数运算。
  3. 布尔值(Boolean)
    Shell没有原生的布尔类型,但你可以使用整数(0表示假,非0表示真)或字符串(空字符串表示假,非空字符串表示真)来模拟布尔值。在条件判断语句(如if语句)中,你可以根据这些模拟的布尔值来决定是否执行某个代码块。
  4. 浮点数(Float)和双精度浮点数(Double)
    Shell本身不直接支持浮点数运算。但是,你可以通过调用外部程序(如bcawkperlpython等)来处理浮点数和双精度浮点数。这些外部程序提供了更丰富的数学运算功能,包括浮点数运算。
    • bc是一个任意精度的计算器语言,它允许你设置小数点后的位数(即精度),并执行浮点数运算。
    • awk是一个强大的文本处理工具,它内置了对浮点数的支持,并提供了printf函数来格式化输出浮点数。

变量的作用范围

在编程中,变量的作用范围(也称为变量的作用域)指的是变量在程序中可以被访问和修改的区域。根据变量的作用范围,变量可以被分为局部变量和全局变量两大类。

局部变量(Local Variables)

局部变量是在函数或代码块内部定义的变量。它们的作用范围仅限于定义它们的函数或代码块内部。一旦离开这个函数或代码块,局部变量就不再可用(即它们会被销毁)。这意味着局部变量只在定义它们的函数或代码块执行时存在,并且每个函数或代码块的局部变量都是独立的,互不影响。
特点

  • 只在定义它们的函数或代码块内部可见和可用。
  • 函数或代码块执行完毕后,局部变量会被销毁。
  • 不同的函数或代码块可以定义同名的局部变量,这些变量互不影响。

全局变量(Global Variables)

全局变量是在函数或代码块外部定义的变量。它们的作用范围是整个程序,即在整个程序中都可以访问和修改全局变量。全局变量在程序启动时被创建,在程序结束时被销毁。
特点

  • 在整个程序中都是可见的。
  • 可以在程序的任何地方被访问和修改(但在某些编程语言中,可能需要特定的声明来在函数内部访问全局变量)。
  • 如果多个函数或代码块需要共享数据,全局变量是一个选择,但过度使用全局变量可能会导致代码难以理解和维护。

注意

  • 局部变量和全局变量的命名可以相同,但在同一个作用域内,局部变量的优先级高于全局变量。这意味着在函数内部,如果定义了与全局变量同名的局部变量,那么在该函数内部访问该变量时,会先访问局部变量。
  • 为了避免命名冲突和提高代码的可读性,建议给局部变量和全局变量使用不同的命名规则或前缀。
  • 在多线程编程中,全局变量的访问需要特别注意线程安全问题,因为多个线程可能会同时修改全局变量的值。

变量的类型

在Shell编程中,变量是存储信息的基本单位,它们可以根据其作用和来源分为环境变量、位置变量和预定义变量。

1. 环境变量(Environment Variables)

定义:环境变量是在操作系统中用来指定操作系统运行环境的一些参数。它们是在操作系统中一个具有特定名字的对象,包含了一个或多个应用程序所将使用到的信息。环境变量对系统内的所有用户进程都是可见的,可以被子进程继承。
常见环境变量

  • PATH:存储了所有命令所在的路径,当要求系统运行一个程序而没有给出其完整路径时,系统会在PATH指定的路径中查找该程序。
  • HOME:用户登录时的主目录。
  • USERUID:当前用户的用户名和用户ID。
  • HOSTNAME:当前主机名。
  • PWD:当前工作目录的路径。
  • PS1:定义系统提示符的变量,用于显示命令行的提示符。
  • LANG:当前语言设置。

设置与查看

  • 在Unix/Linux系统中,可以使用export命令设置环境变量,如export PATH=$PATH:/new/path
  • 使用echo命令结合$符号查看环境变量的值,如echo $PATH

2. 位置变量(Positional Variables)

定义:位置变量主要是用来向脚本或程序中传递参数或数据的。它们在脚本或程序中被自动赋值,其名称和作用是固定的,不能自定义。
常见的位置变量:

  • $0:表示当前执行的脚本或命令的名称(包括路径)。
  • $1$9:分别代表传递给脚本或命令的第一个到第九个参数。
  • ${10} 及以上:对于超过9个的参数,需要使用大括号{}来明确变量的界限,如${10}${11}等。
  • $*:表示传递给脚本的所有参数,但是将所有参数视为一个整体(即一个字符串)。当$*被双引号(")包围时,它会将所有的参数视为一个单一的字符串。
  • $@:也表示传递给脚本的所有参数,但是与$*不同的是,$@将每个参数视为独立的字符串。当$@被双引号(")包围时,它会保留每个参数作为独立的字符串。
  • $#:表示传递给脚本的参数的个数。

位置变量的使用示例:
假设有一个名为example.sh的脚本,内容如下:

#!/bin/bash
echo "脚本名称: $0"
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "所有参数个数: $#"
echo "所有参数作为整体: $*"
echo "所有参数独立显示: $@"

执行该脚本并传递一些参数,如:

./example.sh arg1 arg2 arg3

输出将会是:

脚本名称: ./example.sh
第一个参数: arg1
第二个参数: arg2
所有参数个数: 3
所有参数作为整体: arg1 arg2 arg3
所有参数独立显示: arg1 arg2 arg3

注意:当$*$@不加双引号时,它们在大多数情况下表现相似,但在被双引号包围时,它们的行为会有所不同。
进阶版使用:

  • 处理超过9个的参数:使用${10}${11}等形式来访问超过9个的参数。
  • 在循环中处理所有参数:可以使用for循环结合$@$*(但通常推荐使用$@)来遍历所有参数。
  • 参数扩展和修改:可以使用Shell的参数扩展功能来对位置变量的值进行修改或扩展。

注意:

  • 在编写Shell脚本时,应该注意参数的数量和顺序,因为位置变量是根据它们在命令行中出现的顺序来命名的。
  • 当处理不确定数量的参数时,应该使用$#来检查参数的个数,以避免潜在的错误。
  • 在使用$*$@时,要注意它们在被双引号包围时的行为差异,并根据需要选择使用。

3. 预定义变量(Predefined Variables)

定义:预定义变量是Bash(或其他Shell)已经定义好的变量,它们的名称和作用都是固定的,用户不能修改其名称,但可以在脚本或命令行中引用它们的值。
常见预定义变量

  1. $0:当前执行的脚本或命令的名称(包括路径)。在脚本中,它通常用于输出脚本自身的名称。
  2. $1$9:位置参数,分别代表传递给脚本或命令的第一个到第九个参数。超过9个的参数可以通过${10}${11}等方式访问。
  3. $*$@:都代表传递给脚本的所有参数,但在双引号中引用时行为不同。$*将所有参数视为一个整体(一个字符串),而$@将每个参数视为独立的字符串。
  4. $#:位置参数的数量,即传递给脚本的参数个数。
  5. $$:当前Shell进程的PID(进程ID)。这是一个非常重要的变量,用于唯一标识当前运行的Shell进程。
  6. $!:后台运行的最后一个进程的PID。这在你需要知道某个后台进程的ID以便稍后对其进行管理时非常有用。
  7. $?:上一条命令的退出状态。如果命令成功执行,则$?的值通常为0;如果命令执行失败,则$?的值为非0值。这个变量在条件判断中非常有用。
  8. $-:显示Shell使用的当前选项,这与set命令的功能相同。它可以用来查看或修改Shell的行为选项。

使用:预定义变量为Shell编程提供了许多便利,它们允许脚本或命令获取关于当前环境或之前操作的信息。

补充:自定义变量

定义:

  • 变量名:自定义变量的名称可以由字母、数字和下划线组成,但不能以数字开头。为了避免与系统命令或环境变量冲突,建议变量名具有一定的描述性和可读性。
  • 赋值:定义变量时,使用等号(=)将变量名与变量值连接起来,注意等号两边不能有空格。如果变量值中包含空格、特殊字符(如*、?、$等),则需要用引号(单引号或双引号)将变量值括起来。

示例:
定义一个名为my_var的自定义变量,并赋予它值"Hello, world!",可以这样做:

my_var="Hello, world!"

引用:

  • 调用变量:在Shell中,要引用(或称为“展开”)自定义变量的值,需要在变量名前加上美元符号($)。例如,要打印上面定义的my_var变量的值,可以使用:
echo $my_var

或者,为了防止变量名与后面紧跟的字符混淆,可以使用花括号将变量名括起来:

echo ${my_var}

特性:

  • 作用域:自定义变量默认只在定义它们的shell进程及其子进程中有效。一旦shell进程结束,这些变量也将不再存在。
  • 修改和覆盖:可以通过重新赋值来修改自定义变量的值,新的值会覆盖旧的值。
  • 只读变量:可以使用readonly命令将自定义变量设置为只读,之后就不能再修改这个变量的值了。

查看和取消:

  • 查看变量:可以使用set命令(不带任何选项)来查看当前shell环境中定义的所有变量,包括自定义变量和环境变量。但更常用的是通过echoprintenv(针对环境变量)命令来查看特定变量的值。
  • 取消变量:可以使用unset命令来取消(或称为“删除”)自定义变量,之后这个变量将不再存在,也不能再引用它的值了。

注意:

  • 定义变量时,避免使用与系统命令或保留关键字相同的名称,以防止冲突。
  • 在引用变量时,注意特殊字符和空格的处理,必要时使用引号。
  • 自定义变量是Shell脚本编程中非常灵活和强大的工具,合理利用它们可以大大提高脚本的编写效率和可读性。

变量中的符号

在Shell脚本编程中,各种符号和引号扮演着重要的角色,它们定义了变量的处理方式、表达式的求值方式以及命令的执行方式。

基础符号

  1. 双引号 (" "): 双引号允许在字符串中引用变量(变量会被解析成其值),同时允许在字符串中包含转义字符(如\n表示换行)。但双引号内的变量名周围如果有空格,则空格也会被视为字符串的一部分。
  2. 单引号 (’ '): 单引号中的字符会原样输出,不会进行变量替换或命令替换。单引号内的所有字符都被视为字符串的组成部分,包括空格和特殊字符。
  3. 小括号 (( )): 在shell中,用于创建子shell,定义数组。在正则表达式中,用于捕获组,可以匹配并记住匹配的字串。
  4. 中括号 ([ ]): 用于条件测试和数组索引。在条件测试中,它用于比较数字或字符串是否满足某个条件(如[ $a -eq $b ])。在数组索引中,用于指定数组中的元素(如${array[index]})。在正则表达式中,用于定义字符集,匹配中括号中的任意一个字符。
  5. 大括号 ({ }): shell中用于扩展字符串或者序列,也用于定义代码块。在正则表达式中不常用,用于扩展的正则表达语法中可能表示的数量范围。
  6. 双中括号 ([[ ]]): 在bash等shell中,用于更强大的条件测试,是更强大的引用。是一种比单中括号更强大的条件表达式,支持模式匹配等特性(如[[ $a == z* ]])。
  7. 双小括号 (( )): 专门用于算术运算,支持算术比较,并且算术表达式中的变量可以自动转换为整数。双小括号是bash shell的扩展。

弱引用与强引用

在Shell脚本中,弱引用和强引用主要涉及变量的处理方式:

弱引用

  • 定义:使用${var}$var的形式来引用变量。
  • 特点
    • 允许变量扩展,即如果变量存在,它的值会被替换到引用处。
    • 保留特殊字符的字面意义,特殊字符不会被Shell解释为命令或参数分隔符。
  • 示例
    name="World"
    echo "Hello, $name!"  # 输出: Hello, World!
    

强引用

  • 定义:使用单引号' '来引用内容。
  • 特点
    • 阻止任何变量扩展,变量名会被视为普通文本。
    • 阻止特殊字符的解释,所有内容都被视为普通文本。
  • 示例
    name="World"
    echo 'Hello, $name!'  # 输出: Hello, $name!
    

总结来说,弱引用允许变量扩展和特殊字符的字面解释,而强引用则完全阻止这些行为,确保内容按原样输出。

变量的运算

数值运算

1. 使用expr命令

expr命令是一个用于执行整数算术运算的命令行工具。它也可以用于字符串操作和其他功能,但在这里我们只关注算术运算。

a=5
b=3
c=$(expr $a + $b)
echo $c  # 输出 8

注意:expr命令中的运算符(如+-*/)和变量之间需要有空格。

2. 使用双小括号(( ))

双小括号(( ))是Bash Shell的一个扩展,用于执行算术运算。它提供了比expr更自然和灵活的语法。

a=5
b=3
((c = a + b))
echo $c  # 输出 8
# 或者,更常见的是
((c = $a + $b))
echo $c  # 输出 8
# 或者使用 $(( )) 来进行算术扩展
c=$((a + b))
echo $c  # 输出 8

注意:在(( ))中,变量名前的$符号是可选的,但在使用$(( ))进行算术扩展时,变量名前的$是必须的。

3. 使用let命令

let命令也是Bash Shell中用于执行算术运算的命令。它的语法比较接近C语言中的赋值语句。

a=5
b=3
let c=a+b
echo $c  # 输出 8
# 或者使用 $ 符号
let c=$a+$b
echo $c  # 输出 8

注意:在let命令中,变量名前的$符号是可选的,但加上它也不会出错。

4. 使用bc命令

对于更复杂的算术运算(如浮点运算),可以使用bc命令。bc是一个任意精度的计算器语言。

a=5
b=3
c=$(echo "$a / $b" | bc)
echo $c  # 输出 1.6666...(根据bc的配置,可能会有不同的精度)

# 对于浮点运算,可以设置bc的小数点后的位数:
c=$(echo "scale=2; $a / $b" | bc)
echo $c  # 输出 1.67

#scale是一种特殊的变量可以用于指定小数位的精度:
scale=2
result=$(echo "scale=$scale;10/3" | bc )
echo=result
3.33

补充

在Shell脚本中,特别是Bash Shell,i++i--++i 这样的运算符通常不直接用在Shell脚本的算术表达式中,因为这些是C语言和其他一些编程语言中常见的自增(increment)和自减(decrement)运算符。然而,Bash Shell支持算术扩展,并且可以通过一些方式模拟这些运算符的行为。
在Bash中,没有直接的前缀(++i)或后缀(i++i--)自增自减运算符,但你可以通过算术扩展和赋值语句来实现相同的效果。

后缀自增和自减(i++i--

在Bash中,你可以通过先使用变量的值,然后再将其增加或减少来实现后缀自增自减的效果。但是,由于Bash的语法限制,你通常需要在两条语句中完成这个操作:

i=5
# 后缀自增
echo $i    # 输出 5
((i++))    # 或者 let i=i+1
echo $i    # 输出 6

# 后缀自减
((i--))    # 或者 let i=i-1
echo $i    # 输出 5(如果之前i是6的话)

前缀自增(++i

前缀自增在Bash中可以通过在算术扩展中先增加变量的值,然后再使用它的值来实现:

i=5
# 前缀自增
((++i))    # 或者 let i=i+1,但这里主要是展示++i的效果
echo $i    # 输出 6

条件运算

test命令(也称为[ ])是Shell脚本中用于进行条件测试的命令。它用于检查某个条件是否成立,并根据结果返回一个退出状态码(exit status)。如果条件成立,test命令返回0;如果条件不成立,返回非0值。

test命令的语法:

test condition

或者使用方括号形式:

[ condition ]

常用的test命令条件:

  1. 文件测试
    [ 操作符 文件/目录 ]
    • -e:文件存在
    • -f:普通文件存在
    • -d:目录存在
    • -r:文件可读
    • -w:文件可写
    • -x:文件可执行
  2. 字符串测试
[ 字符串1 = 字符串2 ]或者[ 字符串1 == 字符串2 ]
[ 字符串1 != 字符串2]
  • ===:字符串相等
  • !=:字符串不等
  • -z:字符串长度为0
  • -n:字符串长度不为0
[ -z "字符串" ]#检查是否为空(未定义或者赋空值的变量视为空串)
[ -n "字符串" ]#检查是否字符串存在
  1. 整数测试
[ 整数变量1 操作符 整数变量2]
  • -eq:整数相等
  • -ne:整数不等
  • -gt:整数大于
  • -lt:整数小于
  • -ge:整数大于等于
  • -le:整数小于等于
  1. 逻辑测试
[ 表达式1 ] 操作符 [ 表达式2 ]
   命令1 操作符 命令2
  • -a&&:逻辑与
  • -o||:逻辑或
  • -!!:逻辑非
    &&、|| 能正常存在于[[]]条件判断中,但[]中会报错:
a=5
[$a -ne 1] &&[ $a != 2] 等同于 [ $a -ne | -a $a != 2 ]

示例:

# 文件测试
if test -f "myfile.txt"; then
  echo "File exists"
fi

# 字符串测试
name="World"
if [ "$name" = "World" ]; then
  echo "Hello, World!"
fi

# 整数测试
a=5
b=3
if [ $a -eq $b ]; then
  echo "a equals b"
else
入代码片
  echo "a does not equal b"
fi

需要注意的是,在使用方括号[ ]时,左右两边需要有空格,否则会被解释为文件名。例如,[ $a -eq $b ]是正确的,而[$a -eq $b]是不正确的。

标签:脚本,Shell,入门,echo,shell,参数,Linux,字符串,变量
From: https://blog.csdn.net/Karoku/article/details/141555692

相关文章

  • WebGL入门(014):WebGLActiveInfo 简介、使用方法、示例代码
    还是大剑师兰特:曾是美国某知名大学计算机专业研究生,现为航空航海领域高级前端工程师;CSDN知名博主,GIS领域优质创作者,深耕openlayers、leaflet、mapbox、cesium,canvas,webgl,echarts等技术开发,欢迎加底部微信(gis-dajianshi),一起交流。No.内容链接1Openlayers【入门教程】-......
  • 一文详细了解初学者怎么入门大语言模型(LLM)?
    关于如何入门LLM,大多数回答都提到了调用API、训练微调和应用。但是大模型更新迭代太快,这个月发布的大模型打榜成功,仅仅过了一个月就被其他模型超越。训练微调也已经不是难事,有大量开源的微调框架(llamafactory、firefly等),你只要懂部署,配置几个参数就能启动训练。甚至现在有大......
  • 计算机网络信息安全,零基础入门到精通,收藏这一篇就够了!
    01网络安全概述安全性威胁计算机网络通讯过程中,主要有两种威胁。•主动攻击•被动攻击具体攻击的位置如下图。从汽车电子的角度举个例子,大部分的软件工程师,应该都干过下面两件事。•被动攻击大家都做过的,“对标,抄袭”买来对标的车,找个一分二的线,不知道从哪弄来的......
  • xshell使用跳板机ssh连结远程后使用SFTP
    xshell连结跳板机后,再使用ssh连结到真实机器,SFTP只能显示原跳板机的目录,不能显示真实目录.可以使用隧道,代理来显示真实目标机器的目录.参考:https://blog.csdn.net/qq_43797186/article/details/1236690711.在原跳板机的ssh连结,增加隧道ssh连结属性->连结->SSH->隧道......
  • STM32与Linux串口双向通信
    STM32与linux双向串口通信实验    本文记录STM32与linux双向串口通信,包含stm32发送、Linux阻塞式接收;Linux发送,STM32阻塞式接收;本实验的目的在于调通数据链路,为之后使用奠定基础。实验平台为:    STM32方面用的是STM32H723ZGT6为核心的开发板;开发环境为VS......
  • linux常用命令
    一、netstat系列netstat-tn|awk'{print$6}' |sort|uniq-c这个命令由几个部分组成,每一部分都完成特定的任务,最终的目的是统计网络连接的状态。我们可以将其分解成以下几部分:netstat-tn:netstat 是一个用于显示网络连接、路由表和网络接口信息的命令。-t 选......
  • 10种常见的黑客攻击、满足你的黑客梦,零基础入门到精通,收藏这一篇就够了
    1.跨站脚本(XSS)跨站脚本攻击是最为常见的一类网络攻击,它针对的是网站的用户,而不是web应用本身。恶意黑客在有漏洞的网站里注人一段代码,然后网站访容执行这段代码。此类代码可以人侵用户账户,激活木马程序,或者修改网站内容,诱骗用户给出私人信息。​设置web应用防火墙(W......
  • 什么是linux的复合命令
    Linux中的复合命令(CompoundCommands)是一种在shell(如bash)中允许将多个命令组合成一个逻辑单元进行执行的方式。这种方式允许你通过特定的语法结构,将多个命令组织起来,以实现更复杂的逻辑处理。复合命令可以帮助你减少脚本中的重复代码,提高脚本的可读性和可维护性。Linuxshell(特别......
  • Vulkan入门系列17 - 多重采样( Multisampling)
    一:概述        我们的程序现在可以加载多个级别的纹理,从而解决了在渲染远离观察者的物体时出现的伪影问题。现在图像变得平滑多了,但仔细观察,你会发现绘制的几何图形边缘呈现锯齿状。这在我们早期渲染一个四边形的程序中尤为明显:        这种不希望有的效果......
  • 【Linux】进程|进程的查看与管理|创建进程
    目录1️⃣进程的概念(Process)1.什么是进程?2.多进程管理3.描述进程-PCB2️⃣进程的查看与管理1.使用指令查看进程2.通过系统调用函数查看pid3.杀掉进程4.ppid(父进程id)3️⃣创建进程fork()的工作原理父进程与子进程的关系写时复制(Copy-on-Write)fork()的使用1️⃣进......