Shell 编程基础与变量

Shell

Shell(壳)是计算机操作系统中的一种用户界面,它为用户提供了与操作系统内核和系统资源进行交互的途径。Shell可以是一种命令行界面(CLI,Command-Line Interface)或图形用户界面(GUI,Graphical User Interface),用户可以通过Shell执行命令、运行程序、管理文件和系统等。

在Linux和类Unix系统中,Shell是一个解释器,它解释和执行用户输入的命令,然后将这些命令传递给操作系统内核执行。

程序组成

程序:算法+数据结构

  • 数据:是程序的核心
  • 算法:处理数据的方式
  • 数据结构:数据在计算机中的类型和组织方式

编程风格

过程式:以指令为中心来组织代码,数据服务于指令。代表:C语言,bash。

过程式编程语言三种执行逻辑:

  • 顺序执行:程序按从上到下顺序执行。
  • 选择执行:程序执行过程中,根据条件的不同,进行选择不同分支继续执行。
  • 循环执行:程序执行过程中需要重复执行多次某段语句。

对象式:以数据为中心来组织代码,指令服务于数据。代表:Java,C++,Python。

  • 类(class):实例化对象,method

编程语言的分类

根据运行方式

  • 编译运行:源代码 → 编译器(编译)→ 程序文件
  • 解释运行:源代码 → 运行时启动解释器,由解释器边解释边运行

根据启编译过程中功能的实现是调用库还是调用外部的程序文件

  • shell脚本编程:利用系统上的命令及编程组件进行编程
  • 完整编程:利用库或编程组件进行编程

shell 脚本的用途和应用场景

用途

  • 自动化常用命令
  • 执行系统管理和故障排除
  • 创建简单的应用程序
  • 处理文本或文件

应用场景

  • 重复性操作
  • 交互性任务
  • 批量事务处理
  • 服务运行状态监控
  • 定时任务执行

常见的shell解释器

Linux系统中的Shell 是一个特殊的应用程序,它介于操作系统内核与用户之间,充当一个"命令解释器"的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出结果。 它是用户使用 Linux 的桥梁。

Shell 既是一种命令语言,又是一种程序设计语言。

常见的 Shell 解释器程序有很多种,使用不同的 Shell 时,其内部指令、命令行提示符等方面会存在一些区别。通过/etc/shell 文件可以了解当前系统所支持的 Shell 脚本种类。

linux 中常见的shell

  • bash:基于GUN的框架下发展的shell
  • csh:类似C语言的shell
  • tcsh:整合了csh 提供了更多功能
  • sh:已经被bash替换
  • nologin:让用户无法登录

bash(/bin/bash)是目前大多数 Linux 版本采用的默认 shell。

bash特性

  • 支持快捷键:比如 ctrl+c 强制终止进程 、 ctrl+l 清屏 、Tab补齐 等等。
  • 支持查看历史命令(history)
  • 支持别名(alias)
  • 标准输入和标准输出的重定向
  • 管道符
  • 文件名通配机制
  • 支持命令hash
  • 支持变量

这些功能都是bash特有的,其他shell环境没有这些功能,或者说没有这么全,所以bash取代sh成为了Linux的默认shell。

shell脚本基本结构

shell脚本就是将各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。

将要执行的命令按顺序一一列出,保存到一个文本文件,最后自动执行。 执行脚本需要x权限,也可以使用绝对路径来执行。 可结合各种Shell控制语句以完成更复杂的操作。

脚本的构成:

脚本申明(申明解释器) :第一行开头 "#!/bin/bash",表示此行以下的代码语句是通过/bin/bash程序来执行。还有其他类型的解释器,比如 #/usr/bin/python、#!/usr/bin/expect 。

注释信息: 以"#"开头的语句表示为注释信息,被注释的语句在脚本运行时不会被执行。

可执行语句: 如echo命令,用于输出" "之间的字符串。

脚本的执行方式

指定路径去执行文件,文件需要有执行权限。

绝对路径。如:/root/hello.sh

相对路径。如:./hello.sh

指定解释器去执行(bash 脚本名),不需要执行权限。

  • bash 脚本名。如:bash hello.sh
  • "source 脚本名" 或 " . 脚本名"。 //不会启动子shell环境

执行脚本时的shell环境:

  • source和 . 执行脚本时,会在当前shell环境中执行脚本。
  • bash、绝对路径、相对路径 执行脚本时,会创建一个子shell环境,并在这个子shell环境中执行脚本。
  • 不建议使用source来执行脚本,可能会影响一些资源配置。
  • 脚本中的空白行会被解释器忽略。
  • 脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略。此即为注释行。

脚本错误调试

脚本错误类型:

  • 命令错误: 命令错误不会影响接下来的命令,之后的命令会继续执行。
  • 语法错误: 会导致后续的命令不执行。造成脚本中一部分命令已执行,一部分未执行。
  • 逻辑错误: 执行后的效果不是自己想要的。需要自己去排查。

bash -n 脚本名称 //只检查语法错误,不真正执行脚本。定位的错误行可能不准确。
bash -x 脚本名称 //显示每个命令的执行过程,方便发现逻辑错误

重定向与管道符

由于Shell脚本"批量处理"的特殊性,其大部分操作过程位于后台,不需要用户进行干预,因此要学会提取、过滤执行信息变得十分重要,所以我们需要重定向和管道。

标准输入与输出

交互式硬件设备

  • 标准输入:从该设备接收用户输入数据。
  • 标准输出:通过该设备想用户输出数据。
  • 标准错误:通过该设备报告执行出错信息。

重定向

重定向的意思就是,不通过标准输出到默认屏幕上,而是输出到你指定的位置。

输入重定向

符号 作用
命令 < 文件 从指定的文件读取文件,而不是从键盘输入
命令 << 分界符 从标准输入中读入,直到遇见分界符才停止
命令 < 文件1 > 文件2 将文件1 作为命令的标准输入并将标准输出到文件2

输出重定向

符号 作用
命令 > 文件 将标准输出结果保存到指定的文件中(覆盖原有内容)
命令 >> 文件 将标准输出结果追加到指定的文件尾部
命令 2> 文件 将错误输出信息保存到指定文件中(覆盖原有内容)
命令 2>> 文件 将错误输出信息追加到指定文件尾部
命令 > 文件 2>&1 混合输出,将标准输出与错误输出保存到文同一个文件中
命令 2> 文件 1>&2 混合输出,将标准输出与错误输出保存到文同一个文件中
命令 &> 文件 混合输出,将标准输出与错误输出保存到文同一个文件中
命令 >& 文件 混合输出,将标准输出与错误输出保存到文同一个文件中
  • &表示混合,&> 和 >& 都表示将标准输出和错误输出重定向到同一个文件。
  • 命令 > 文件 2>&1,表示把错误输出2重定向给前面的标准输出1 (前面的1被省略了),即将错误输出和标准输出保存到同一个文件中。

管道符

管道符的作用是连接两个命令,将第一个命令的标准输出作为第二个命令的标准输入。 同一行命令中可以使用多个管道符。

linux下的管道符使用"竖杠"表示:| 。

格式:命令A | 命令B

变量

  • 变量即在程序运行过程中它的值是允许改变的量。
  • 变量是用一串固定的字符串去表示不固定的内容。
  • 变量表示命令的内存空间,将数据放在内存空间中,通过变量名引用,获取数据。

变量的作用:

  • 用来存放系统和用户需要使用的特定参数(值)。
  • 变量名:使用固定的名称,由系统预设或用户定义。
  • 变量值:能够根据用户设置、系统环境的变化而变化。

变量类型

变量赋值: 变量名=变量值(name=value)

根据变量的生效范围

环境变量(全局变量):全局生效,在任何bash环境中都可以识别。

局部变量:生效范围为当前shell进程。对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效。

本地变量:生效范围为当前shell进程中某代码片断,通常指函数。 只能在定义它们的函数/脚本内部中使用。

根据是否由系统定义

内置变量:由系统维护,用于设置工作环境。如PS1,PATH,HISTSIZE, HOSTNAME,USER。 自定义变量:由用户自己定义、修改和使用。

特殊变量

环境变量(全局变量):全局生效,在任何bash环境中都可以识别。:

只读变量:read only, 只可以读取不可以更改 。

位置变量: 通过命令行给脚本传递参数 。n(n是正整数),n(n是正整数),n(n是正整数),{10} 要加花括号。

预定义变量用来保持脚本程序的执行信息。

  • $0 :当前脚本名称(如果是软链接,显示当前软链接文件名)。
  • $? :查看上一次命令的执行状态,返回0为正常,非0为错误。
  • $* :返回所有参数,当整体返回。
  • $@ :返回所有参数,当个体返回。
  • $# :获取当前shell命令行中参数的总个数。
  • $_ :在此之前执行的命令或脚本的最后一个参数。
  • '$$' :获取当前进程的PID。

变量作用范围

默认情况下,新定义的变量只在当前的shell环境中有效,因此称为局部变量,当进入子程序或新的shell环境中,局部变量将无法再起作用。 可以通过内部命令export将指定的变量为全局变量(即环境变量),使用户定义的变量在所有子shell环境中可以继续使用。

设置全局变量:

  • export name=value
  • declare -x name=value

将局部变量转变为全局变量:

  • export name

特殊符号

js 复制代码
双引号" ":会把引号的内容当成整体来看待。强引用,识别变量,允许通过$符号引用其他变量值。
单引号' ':会把引号的内容当成整体来看待。弱引用,禁止引用其他变量值,单引号内的内容都会被认为是普通字符。
反撇号` ` 和 $() :调用命令执行后输出的结果。如果存在嵌套,不能使用反撇号。
花括号{  } :定义变量范围。 echo ${color}${price}

局部变量

定义变量: 变量名=变量值

引用变量 : <math xmlns="http://www.w3.org/1998/Math/MathML"> 变量名或 变量名 或 </math>变量名或{变量名}

查看变量

  • echo $变量名:查看单个变量
  • set:查看所有变量,包括局部变量和环境变量

取消变量: unset 变量名

作用范围: 仅在当前shell环境中有效,无法在子shell环境中使用。

环境变量

系统内置环境变量

由系统提前创建,用来设置用户的工作环境。

使用env命令查看所有环境变量

  • $PATH 表示可执行文件的默认路径
  • $USER 表示用户名称
  • $HOME 表示用户的宿主目录
  • $LANG 表示语言和字符集
  • $PWD 表示当前所在工作目录

环境变量的特性

  • 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量。
  • 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程。
  • 一般只在系统配置文件中使用,在脚本中较少使用。

只读变量

在定义shell变量时,默认定义的变量是可以被修改的,但有一种变量是不能修改的,就是只读变量。

只读变量只能被赋值一次。只读变量在取得初始值之后,只能进行读取操作,不能重新赋值或删除。

位置变量

位置变量也称为位置参数。

使用$n表示,n为数字序列号,且必须为整数。

如: <math xmlns="http://www.w3.org/1998/Math/MathML"> 1 、 1、 </math>1、2、...、 <math xmlns="http://www.w3.org/1998/Math/MathML"> 9 、 9 、 </math>9、{10}、${11}。

两位数需要加花括号{},不然 <math xmlns="http://www.w3.org/1998/Math/MathML"> 10 会被识别为: 10会被识别为: </math>10会被识别为:1和0 。

预定义变量

预定义变量是系统定义好的变量,用来保持脚本程序的执行信息。

可以直接使用这些变量,不能直接为这些变量赋值。

变量 作用
$? 表示前一条命令执行后的返回状态。返回值为 0 表示执行正确,返回任何非 0值均表示执行出现异常
$* 表示所有位置参数的内容。当整体返回。(将输入的参数作为一个单词)
$@ 表示所有位置参数的内容。当个体返回。可作为数组。(将参数内容分割成n份,每份作为独立个体)
$# 表示命令行中位置参数的总个数
$0 表示当前脚本名称(如果是软链接,显示当前软链接文件名)
$_ 表示在此之前执行的命令或脚本的最后一个参数
$$ 获取当前进程的PID
js 复制代码
$* 和 $@的区别:

不加双引号的话,$* 和 $@ 都代表脚本后面跟的所有参数。
加上双引号的话,"$*"会把所有参数当作一个整体去看待(此时参数数量为1),"$@"会把脚本后面跟的每一个参数当作一个个体去看待。

$?

read

read可以从键盘输入变量值,即将键盘输入的内容变成变量值。

选项 作用
-p 后面跟提示信息,即在输入前打印提示信息
-s 安静模式,在输入字符时不再屏幕上显示,例如密码
-t 后面跟秒数,定义输入字符的等待时间
-n 后跟一个数字,定义输入文本的长度
-a 后跟一个变量,该变量会被认为是个数组
相关推荐
韩楚风2 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
陈苏同学2 小时前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm
Ambition_LAO2 小时前
解决:进入 WSL(Windows Subsystem for Linux)以及将 PyCharm 2024 连接到 WSL
linux·pycharm
Pythonliu72 小时前
茴香豆 + Qwen-7B-Chat-Int8
linux·运维·服务器
你疯了抱抱我2 小时前
【RockyLinux 9.4】安装 NVIDIA 驱动,改变分辨率,避坑版本。(CentOS 系列也能用)
linux·运维·centos
追风赶月、2 小时前
【Linux】进程地址空间(初步了解)
linux
栎栎学编程2 小时前
Linux中环境变量
linux
挥剑决浮云 -3 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记
小O_好好学4 小时前
CentOS 7文件系统
linux·运维·centos
哲伦贼稳妥4 小时前
一天认识一个硬件之机房地板
运维·网络·经验分享·其他