欢迎光临
我们一直在努力

Linux Shell 编程:变量与规范

Linux Shell编程规范与变量

一、Shell脚本基础认知

1. Shell的核心作用

Shell是Linux内核与用户之间的命令解释器,负责接收用户输入的指令并解析,将操作请求传递给内核执行,最终把执行结果反馈给用户。它是Linux系统运维的核心工具,常见的Shell解释器有/bin/sh、/bin/bash(绝大多数Linux系统默认)、/bin/zsh等,通过cat /etc/shells可查看当前系统支持的Shell类型。

2. Shell脚本的价值

Shell脚本是将一系列Linux命令按逻辑顺序整合的可执行文本文件,能实现任务的自动化、批量处理,有效减少重复操作,降低人为失误,提升Linux系统管理和运维的效率,适用于定时备份、服务启停、批量部署等场景。

3. 脚本的基本编写规范

  • 脚本声明:第一行必须写#!/bin/bash(指定脚本的解释器为bash),若用其他Shell需对应修改,如#!/bin/zsh;

  • 注释规范:以#开头的行为注释,单行注释直接写# 注释内容,多行注释可使用:<<EOF 注释内容 EOF;

  • 命名规范:脚本文件建议以.sh为后缀,名称由字母、数字、下划线组成,见名知意(如backup_data.sh、check_disk.sh);

  • 缩进规范:脚本内的代码块(如循环、判断)建议用4个空格缩进,提升可读性,避免使用制表符(Tab)。

  • 4. 脚本的执行方式

    假设编写好脚本test.sh,需先通过chmod +x test.sh添加可执行权限,主要执行方式有3种:

  • 绝对/相对路径执行:./test.sh(相对路径)、/root/test.sh(绝对路径),要求脚本有执行权限;

  • 指定解释器执行:bash test.sh、sh test.sh,无需脚本的执行权限,直接调用解释器解析;

  • 加载执行:source test.sh或. test.sh,脚本在当前Shell环境执行,而非新建子Shell,适合修改环境变量的脚本。

  • 二、重定向与管道操作

    Shell脚本的输入输出默认依赖键盘(标准输入)和显示器(标准输出/错误),重定向和管道可灵活改变数据的传递方式,是脚本处理数据的基础。

    1. 标准I/O设备标识

    设备名称

    标识符号

    文件编号

    默认设备

    标准输入

    stdin

    0

    键盘

    标准输出

    stdout

    1

    显示器

    标准错误

    stderr

    2

    显示器

    2. 重定向操作

    (1)输出重定向

    将命令的正常结果/错误信息写入文件,而非显示在屏幕,核心符号:

    • >:覆盖重定向,新建文件(无则建)并写入内容,覆盖原有内容;

    • >>:追加重定向,将内容添加到文件末尾,保留原有内容;

    • 2>:错误重定向,仅将命令的错误信息写入文件;

    • &>:混合重定向,将正常结果和错误信息同时写入文件。

    示例:

    ls -l > file_list.txt # 把ls结果覆盖写入file_list.txt
    df -h >> disk_info.txt # 把磁盘信息追加到disk_info.txt
    tar zcf /test.tar.gz /etc 2> error.log # 把tar的错误信息写入error.log
    ls /nonedir &> /dev/null # 把所有结果写入空设备(忽略输出)

    (2)输入重定向

    将命令的输入源由键盘改为文件,核心符号<,适用于交互式命令的自动化执行。

    示例:

    passwd –stdin user < pass.txt # 从pass.txt读取密码,为user设置密码(前提pass.txt中有密码)

    3. 管道操作

    核心符号为|,将左侧命令的标准输出作为右侧命令的标准输入,支持多个管道串联,用于数据的过滤、提取和处理,是Shell脚本中数据处理的核心技巧。

    示例:

    # 提取系统中使用bash的用户名 grep "/bin/bash" /etc/passwd | awk -F: '{print $1}'
    # 提取根分区的磁盘使用率 df -hT | grep "/$" | awk '{print $6}'
    # 统计系统中正在运行的java进程数 ps -ef | grep java | grep -v grep | wc -l

    三、Shell变量的核心使用

    变量是Shell脚本的核心元素,用于存储和管理动态数据,通过变量可让脚本具备灵活性和通用性。Shell变量无需声明类型,直接赋值使用,核心分为自定义变量和特殊变量两大类。

    1. 自定义变量

    由用户自行定义、赋值和使用的变量,默认仅在当前Shell环境有效(局部变量),是脚本中最常用的变量类型。

    (1)定义与赋值

    格式:变量名=变量值,等号两边无空格,变量名规则:以字母/下划线开头,仅包含字母、数字、下划线,区分大小写。

    示例:

    name=Linux version=centos7 num=100

    (2)引用与查看

    格式:$变量名或${变量名},推荐使用${变量名},避免变量名与后续字符混淆;通过echo命令查看变量值。

    示例:

    echo $name # 输出Linux
    echo ${version}6 # 输出centos76,若写$version6则会识别为新变量(无值)
    echo ${name}_${num} # 输出Linux_100

    (3)特殊赋值方式

    针对不同场景的赋值技巧,解决空格、特殊字符、命令结果、交互输入等问题:

  • 双引号"":界定带空格的字符串,支持变量引用($生效);

  • 示例:
    info="Linux ${version}" → echo $info输出Linux centos7

        2.单引号'':界定带特殊字符的字符串,屏蔽所有特殊符号($、\\等均为普通字符);

    示例:
    info='Linux ${version}' → echo $info输出Linux ${version}

    3.反撇号`:当要赋值的内容中包含$,'',\\等具有特殊含义的字符时,应使用单引号括起来。在单引号的范围内,将无法引用其他变量的值,任何字符均作为普通字符看待。但赋值内容中包含单引号(')时,需要使用\\'符号进行转义,以免冲突。

    示例:
    `time$$(date +%Y%m%d)→echo $time`输出当前日期(如20250520)

        3.read命令:交互赋值,提示用户输入内容并赋值给变量,-p设置提示语,-t设置超时时间;

    示例:
    read -p "请输入备份目录:" dir → 用户输入的内容赋值给dir

    (4)变量的作用范围
    • 局部变量:默认定义的变量,仅在当前Shell有效,子Shell无法调用;

    • 全局变量:通过export 变量名将局部变量导出,所有子Shell均可调用,支持定义+导出一步完成。

    示例:

    export PATH=$PATH:/root # 把/root添加到系统命令搜索路径(全局)
    export ip=192.168.1.100 # 定义并导出全局变量ip

    (5)数值变量运算

    Bash默认仅支持整数运算,不支持小数,核心工具为expr和$((运算式))(推荐,语法更简洁),常用运算符:+(加)、-(减)、\\*(乘)、/(除)、%(取余)。

    示例:

    a=10
    b=3
    # expr方式:运算符两边必须有空格,乘法需转义\\*
    expr $a + $b # 输出13
    expr $a \\* $b # 输出30 # $((运算式))方式:无空格要求,无需转义
    echo $((a – b)) # 输出7
    echo $((a % b)) # 输出1
    # 运算结果赋值给变量 sum=$((a + b)) echo $sum # 输出13

    (6)变量的删除

    通过unset 变量名删除已定义的变量,删除后变量无值,只读变量无法删除。

    示例:

    unset name # 删除变量name echo $name # 无输出(变量已删除)

    2. 特殊变量

    由Linux系统和Bash预先定义的变量,用户只能使用,不能修改或新建,分为环境变量、只读变量、位置变量、预定义变量四类,是脚本实现灵活传参、状态判断的关键。

    (1)环境变量

    系统提前创建的变量,用于设置用户工作环境,值由系统自动维护,随用户状态变化而改变,通过env或printenv可查看所有环境变量,核心常用环境变量:

    变量名

    作用

    USER

    当前登录的用户名

    HOME

    当前用户的宿主目录

    PWD

    当前用户的工作目录

    PATH

    系统命令的默认搜索路径

    LANG

    系统的语言和字符集

    HISTSIZE

    系统保存的历史命令条数

    拓展:环境变量的配置文件

    • 全局配置:/etc/profile(对所有用户生效)、/etc/profile.d/(推荐,新建脚本配置);

    • 个人配置:~/.bash_profile、~/.bashrc(仅对当前用户生效);

    • 配置生效:修改后执行source 配置文件立即生效,否则下次登录生效。

    (2)只读变量

    一经定义,值不可修改、不可删除的变量,用于固定关键参数(如日志路径、配置文件路径),通过readonly 变量名定义(可直接定义+只读,或对已有变量设置只读)。

    示例:

    使用readonly命令将变量定义为只读变量,定义之后不能通过再次赋值的方式进行修改
    name=cloud
    readonly name (设置为只读变量)
    echo $name (会显示为cloud)
    name=yun (只读变量不可以被重新赋值)
    unset name (只读变量也不可以被删除)

    unset通常用于删除变量!!!!!!!!!!!!

    (3)位置变量

    用于脚本命令行传参,脚本执行时,将命令行的参数按顺序赋值给位置变量,核心符号:$1、$2、$3…$9(超过9个用${10}、${11}),$0表示脚本本身的名称。

    示例:编写脚本add.sh实现两数相加
    vim addr.sh

    #!/bin/bash
    # 位置变量$1、$2接收命令行传入的两个整数
    sum=$(( $1 + $2 )) echo "$1 + $2 = $sum"

    chmod +x add.sh (给予权限)
    ./add.sh 10 20
    # $1=10,$2=20,输出10 + 20 = 30
    ./add.sh 50 60
    # $1=50,$2=60,输出50 + 60 = 110

    (4)预定义变量

    Bash程序预先定义好的一类特殊变量,用户只能使用预定义变量,而不能创建新的预定义变量,也不能直接为预定义变量赋值。用于获取脚本执行的状态、参数信息,核心常用预定义变量:

    变量名

    作用

    $#

    命令行中位置参数的个数

    $*

    命令行中所有位置参数的内容(视为一个整体)

    $@

    命令行中所有位置参数的内容(视为独立个体,与$*的区别在循环中体现)

    $?

    前一条命令的执行返回状态,0表示执行成功,非0表示执行失败

    $0

    当前执行的脚本/程序的名称

    $$

    当前Shell进程的PID号

    示例:编写脚本param.sh查看预定义变量效果

    #!/bin/bash echo "脚本名称:$0" echo "参数个数:$#" echo "所有参数:$*" echo "上一条命令执行状态:$?"

    执行脚本:

    chmod +x param.sh ./param.sh 10 a Linux # 传入3个参数 # 输出结果 脚本名称:./param.sh 参数个数:3 所有参数:10 a Linux 上一条命令执行状态:0

    四、Shell变量的拓展知识点

    1. 变量的默认值设置

    通过特殊语法为变量设置默认值,解决变量未定义/为空时的脚本异常,核心语法:

    • ${变量名:-默认值}:变量未定义/为空时,使用默认值,不修改原变量;

    • ${变量名:=默认值}:变量未定义/为空时,使用默认值,并将默认值赋值给原变量。

    示例:

    echo ${dir:-/tmp} # 若dir未定义,输出/tmp,dir仍为未定义 echo ${dir:=/tmp} # 若dir未定义,输出/tmp,dir被赋值为/tmp

    2. 变量的字符串处理

    快速对变量的字符串进行截取、替换,无需调用其他命令,提升脚本效率(基础版):

    • 截取:${变量名:起始位置:长度},起始位置从0开始;

    示例:str=LinuxCentos → echo ${str:0:5}输出Linux

    • 替换:${变量名/旧字符串/新字符串}(替换第一个)、${变量名//旧字符串/新字符串}(替换所有);

    示例:str=aaabbb → echo ${str/a/1}输出1aabbb,echo ${str//a/1}输出111bbb

    3. 特殊变量$$*$$@的区别

    两者均表示所有位置参数,但在双引号+循环中体现核心区别:

    • "$*":将所有参数视为一个整体,循环仅执行一次;

    • "$@":将所有参数视为独立个体,循环执行次数等于参数个数。

    示例:

    #!/bin/bash echo "循环遍历$*:" for i in "$*"; do echo $i done echo "循环遍历$@:" for i in "$@"; do echo $i done

    执行./test.sh 1 2 3,输出:

    循环遍历$*: 1 2 3 循环遍历$@: 1 2 3

    五、Shell编程的通用规范

  • 脚本开头:必须写解释器声明#!/bin/bash,并添加脚本说明(注释),包括脚本功能、作者、创建时间、使用方法;

  • 变量命名:局部变量用小写字母(如file_path),全局变量用大写字母(如LOG_PATH),见名知意,避免单字符变量(除循环临时变量i/j);

  • 路径使用:脚本中尽量使用绝对路径,避免相对路径导致的执行路径错误;

  • 错误处理:关键命令后可通过$?判断执行状态,失败时输出提示信息并退出脚本(exit 1);

  • 日志记录:重要脚本建议将执行过程和结果写入日志文件,便于问题排查;

  • 权限控制:脚本执行后建议恢复默认权限,避免过高权限带来的安全风险;

  • 代码复用:将常用的功能(如变量定义、函数)抽离为单独的配置文件,通过source加载使用。

  • 规范脚本示例:

    #!/bin/bash # 脚本功能:批量查看指定目录的文件大小 # 作者:xxx # 创建时间:2025-05-20 # 使用方法:./file_size.sh 目录路径 # 判读参数个数 if [ $# -ne 1 ]; then echo "使用错误!正确方法:./file_size.sh 目录路径" exit 1 fi # 定义变量 DIR=$1 LOG_FILE=/var/log/file_size_$(date +%Y%m%d).log # 判断目录是否存在 if [ ! -d $DIR ]; then echo "错误:目录$DIR不存在!" >> $LOG_FILE exit 1 fi # 执行操作并写入日志 echo "======$(date)======" >> $LOG_FILE du -sh $DIR/* >> $LOG_FILE echo "文件大小统计完成,日志文件:$LOG_FILE"

    赞(0)
    未经允许不得转载:171主机测评 » Linux Shell 编程:变量与规范
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址