Shell脚本编程

一、程序执行方式(解释 / 编译 / 脚本)全解析

1.脚本与解释器
  • 脚本 (比如 .sh.py 这类文件)本身不能直接运行,必须依赖对应的解释器才能执行。
  • 举个例子:.sh 脚本需要 bash 解释器,.py 脚本需要 python 解释器。
  • 运行方式:你得告诉系统 "用什么工具来跑这个脚本",比如 bash my.sh 参数
2. 解释型 vs 编译型
类型 特点 例子
解释型 不需要提前 "翻译" 成机器语言,而是边解释边执行,依赖解释器 .sh.py.class(Java)
编译型 需要先通过编译器把代码 "翻译" 成机器能直接看懂的可执行文件,之后就可以独立运行 .c → 编译成 main.exe / main
3. Java 的特殊之处
  • Java 是 "半编译半解释" 的:
    1. 先把 .java 代码编译成中间文件 .class(字节码)
    2. 再由 Java 虚拟机(JVM) 这个解释器来执行 .class 文件
  • 好处:一次编译,在任何有 JVM 的平台上都能运行(跨平台性)

通俗讲解

你可以把程序想象成不同的菜谱:

  • 解释型(脚本) :就像一本用外语写的菜谱,你必须找个翻译(解释器),一句一句念给你听,你才能跟着做。比如 .sh 脚本需要 bash 这个翻译,.py 需要 python 这个翻译。
  • 编译型 :就像直接把菜谱翻译成了母语的操作手册,你拿到手就能直接照着做,不需要翻译了。比如 .c 代码编译成 main.exe 后,双击就能运行。
  • Java :是先把菜谱翻译成一本国际通用的操作指南(.class 字节码),然后到不同国家时,再由当地的翻译(JVM)来念给你听,所以它既能跨平台,又保留了解释执行的灵活性。

二、Bash 变量、引号与内存映射解析

cpp 复制代码
#!/usr/bin/bash

a=100
str="hello world"
echo "a=$a"
echo "str=$str"
a="$str"
echo "a=$a"
echo 'a=$a'

exit 0
  1. 变量与内存的映射关系

    • 在 Bash 中,变量名(astr)就像内存图里左侧的标签,它们指向右侧内存块里存储的实际值。
    • 当你执行 a=100 时,变量 a 就指向了存储数值 100 的内存块;str="hello world" 时,str 就指向了存储字符串 "hello world" 的内存块。
  2. 变量的动态赋值

    • 当执行 a="$str" 时,变量 a 会改变指向,从原来指向 100 的内存块,改为指向 str 所指向的 "hello world" 内存块。
    • 这就像内存图里,原本连向 100a 箭头,现在被重新连接到了 "hello world" 的位置。
  3. 单引号与双引号的核心区别

    • 双引号 " :会解析其中的变量(如 "a=$a" 会把 $a 替换成它的值),相当于 "引用变量的内容"。
    • 单引号 ' :会原样保留所有字符(如 'a=$a' 里的 $a 不会被解析,直接输出 a=$a),相当于 "引用字面文本"。

面试复习总结

Bash 变量本质:变量名是指向内存值的 "标签",可以随时改变指向。

赋值规则 :直接用 变量名=值,注意等号两边不能有空格。

引号作用:双引号解析变量,单引号保留原样,这是面试高频考点。

脚本结构#!/usr/bin/bash 是指定解释器的 "谢邦行",exit 0 表示脚本正常退出。

三、本地变量、环境变量、参数变量这三者的区别和关系

1. 本地变量

  • 定义:你在脚本里自己定义的变量,作用域仅限当前脚本或 Shell 会话,子进程无法访问。

  • 命名惯例 :按习惯用小写字母(比如 linename),用来和环境变量区分。

  • 类比:就像你自己写的私人便签,只有你能看,别人(子进程)看不到。

  • 例子

    bash

    运行

    复制代码
    # 这是一个本地变量
    user_input="hello"
    echo $user_input

2. 环境变量

  • 定义:Shell 启动时就初始化的全局变量,能被当前 Shell 及其所有子进程继承,通常用来配置运行环境。
  • 命名惯例 :用大写字母(比如 HOMEPATHPS1),和用户自定义的本地变量区分。
  • 类比:像公司公告栏的通知,所有人(子进程)都能看到。
  • 常见例子 (来自你的课本表 2-2):
    • $HOME:当前用户的家目录
    • $PATH:系统搜索命令的目录列表
    • $PS1:命令行提示符
    • $$:当前脚本的进程号

3. 参数变量

  • 定义:脚本运行时,通过命令行传递给它的参数,或者脚本内部的特殊位置参数。

  • 特殊变量$0(脚本名)、$1(第一个参数)、$#(参数个数)等(你的课本表 2-2 里也提到了)。

  • 类比:就像你去餐厅点的菜,是外部传递给脚本的 "输入材料"。

  • 例子

    bash

    运行

    复制代码
    # 假设脚本名为 test.sh,运行时输入:bash test.sh apple banana
    echo "脚本名: $0"          # 输出 test.sh
    echo "第一个参数: $1"     # 输出 apple
    echo "参数总数: $#"       # 输出 2

三者核心区别对照表

变量类型 作用域 命名惯例 来源
本地变量 当前脚本 / Shell 内 小写字母 用户在脚本里定义
环境变量 当前 Shell + 所有子进程 大写字母 系统初始化或用户用 export 导出
参数变量 脚本内部 特殊符号($0$1等) 命令行传递或系统自动生成

面试高频考法

  • :如何让本地变量变成环境变量?→ :用 export 命令,比如 export user_input="hello",这样子进程就能读取到它。
  • $PATH 是什么变量?有什么用?→ :是环境变量,用来告诉系统去哪里找可执行命令,避免每次都写绝对路径。
  • $1$# 是什么变量?→ :是参数变量,$1 代表第一个命令行参数,$# 代表参数的总个数。

四、Shell if 条件判断(面试核心考点全解析)

1.核心说明

Shell 中的 if 条件判断是面试高频考点,核心分为字符串判断、算术判断、文件测试三类,每类都有专属操作符(不能混用),掌握这三类就能应对 90% 以上的 Shell 条件判断面试题。

先记一个通用语法规则(必考!)

所有 if 条件判断的基础格式:

复制代码
if [ 条件表达式 ]; then
    执行命令
elif [ 条件表达式 ]; then
    执行命令
else
    执行命令
fi

✅ 必记细节:[ 左边、] 右边必须加空格(比如 [ $num -gt 5 ] 正确,[$num -gt 5] 报错);条件结尾的 ; 不能少,也可以换行写 then


二、第一类:字符串判断(处理文本 / 变量值)

1. 核心作用

判断两个字符串是否相等、字符串是否为空,是处理用户输入、配置项等文本场景的核心用法。

2. 常用操作符(记口诀:等不等,空非空)

操作符 含义 通俗解释 面试考法示例
= 字符串相等 两个文本完全一样 判断用户输入的指令是否为 "exit"
!= 字符串不相等 两个文本不一样 判断输入的密码和确认密码是否一致
-z 字符串为空(长度 0) 变量里啥都没有 判断用户是否输入了内容
-n 字符串非空(长度 > 0) 变量里有内容 验证配置项是否填写

3. 完整示例(可直接运行)

复制代码
#!/usr/bin/bash
# 模拟用户输入场景
read -p "请输入指令(exit/continue):" cmd

# 1. 判断字符串相等
if [ "$cmd" = "exit" ]; then
    echo "指令相等,退出脚本"
    exit 0
fi

# 2. 判断字符串不相等
if [ "$cmd" != "continue" ]; then
    echo "指令不是continue,请重新输入"
fi

# 3. 判断字符串为空(用户没输入直接回车)
if [ -z "$cmd" ]; then
    echo "你啥都没输入!"
fi

# 4. 判断字符串非空
if [ -n "$cmd" ]; then
    echo "你输入的内容是:$cmd"
fi

4. 面试避坑点(必考!)

  • 变量必须用双引号包裹:比如 [ "$cmd" = "exit" ],如果 cmd 为空,不加引号会变成 [ = "exit" ],直接语法报错;
  • = 两边必须加空格:[ "$cmd"="exit" ] 错误(会把 "$cmd"="exit" 当成一个整体字符串),正确是 [ "$cmd" = "exit" ]
  • 区分 =-eq:字符串相等用 =,数字相等用 -eq,混用会报错。

三、第二类:算术判断(处理数字比较)

1. 核心作用

判断数字的大小、是否相等,比如判断年龄、分数、进程数等数值场景。

2. 常用操作符(记英文缩写,好记!)

操作符 英文全称 含义 通俗解释 面试考法示例
-eq equal 等于 两数一样 判断输入的数字是否为 100
-ne not equal 不等于 两数不同 判断用户输入的数量是否合法
-gt greater than 大于 左边大 判断分数是否大于 60(及格)
-ge greater than or equal 大于等于 左边≥右边 判断年龄是否≥18(成年)
-lt less than 小于 左边小 判断内存使用是否小于 80%
-le less than or equal 小于等于 左边≤右边 判断文件大小是否≤100M

3. 完整示例(可直接运行)

bash

运行

复制代码
#!/usr/bin/bash
read -p "请输入你的分数:" score

# 1. 判断大于等于60(及格)
if [ $score -ge 60 ]; then
    echo "恭喜,及格了!"
    # 2. 嵌套判断:大于等于90为优秀
    if [ $score -ge 90 ]; then
        echo "优秀!"
    fi
# 3. 判断小于60(不及格)
elif [ $score -lt 60 ]; then
    echo "不及格,需要补考"
fi

# 4. 判断等于100(满分)
if [ $score -eq 100 ]; then
    echo "满分!太牛了"
fi

4. 面试避坑点(必考!)

  • 不能用 >/<:Shell 里 > 是重定向符号,< 是输入重定向,比如 [ $score > 60 ] 会创建一个叫 60 的空文件,完全偏离本意;
  • 变量必须是数字:如果 score 输入的是字母,会报错 integer expression expected,面试常问 "如何避免?"------ 可以先判断是否为数字(扩展:if [[ $score =~ ^[0-9]+$ ]]; then);
  • 支持整数,不支持小数:Shell 算术判断只认整数,比较小数需要用 bc 命令(面试扩展考点)。

四、第三类:文件测试(检查文件 / 目录状态)

1. 核心作用

判断文件 / 目录是否存在、是什么类型、有没有读写执行权限,是脚本操作文件的基础(比如备份、删除、执行脚本前的校验)。

2. 常用操作符(记高频,其余了解)

操作符 含义 通俗解释 面试考法示例
-e 文件 / 目录存在 路径是有效的 判断配置文件是否存在
-f 是普通文件(非目录 / 设备) 是实实在在的文件(比如 .sh/.txt) 判断是不是脚本文件
-d 是目录 是文件夹 判断备份目录是否存在
-r 文件可读 当前用户能看这个文件 判断是否有权限读取日志
-w 文件可写 当前用户能修改这个文件 判断是否有权限写入配置
-x 文件可执行 当前用户能运行这个文件 判断脚本是否有执行权限

3. 完整示例(面试经典场景:文件操作前校验)

复制代码
#!/usr/bin/bash
read -p "请输入文件/目录路径:" path

# 1. 先判断路径是否存在
if [ ! -e "$path" ]; then  # ! 表示取反
    echo "路径 $path 不存在!"
    exit 1
fi

# 2. 判断是否为目录
if [ -d "$path" ]; then
    echo "$path 是目录,里面的文件有:"
    ls "$path"  # 列出目录内容
fi

# 3. 判断是否为普通文件
if [ -f "$path" ]; then
    echo "$path 是普通文件"
    # 4. 判断文件是否可读
    if [ -r "$path" ]; then
        echo "你有权限读取这个文件"
    fi
    # 5. 判断文件是否可执行(比如脚本)
    if [ -x "$path" ]; then
        echo "你有权限执行这个文件,执行结果:"
        "$path"  # 运行这个可执行文件
    fi
fi

4. 面试避坑点(必考!)

  • 路径用双引号包裹:如果路径包含空格(比如 My Documents),不加引号会被当成多个参数,报错;
  • 优先用 -e 判存在:先判断路径是否存在,再判断类型 / 权限,避免 "判断不存在的文件的权限" 导致逻辑错误;
  • ! 的用法:取反操作(比如 ! -e "$path" 表示路径不存在),面试常考 "如何判断文件不存在?"。

五、面试高频问答(直接背,能直接答)

1. 问:Shell 中 if 条件里的 [ ] 前后为什么要加空格?

答:因为 [ 是 Shell 的内置命令(等价于 test 命令),空格是用来分隔命令和参数的,如果不加空格,Shell 会把 [$num -gt 5] 当成一个整体字符串,无法识别为条件判断。

2. 问:字符串比较时,变量为什么要加双引号?

答:防止变量为空导致语法错误。比如 cmd 为空时,[ $cmd = "exit" ] 会变成 [ = "exit" ],Shell 无法解析;加双引号后变成 [ "" = "exit" ],能正常判断字符串为空,不会报错。

3. 问:为什么数字比较不能用 >/<,而要用 -gt/-lt?

答:因为 Shell 中 > 是重定向符号,< 是输入重定向符号,比如 [ $score > 60 ] 会创建一个名为 60 的空文件,而不是比较数字大小;-gt/-lt 是 Shell 专门定义的算术比较操作符,能正确识别数字比较逻辑。

4. 问:如何判断一个路径是文件还是目录?

答:先通过 -e 判断路径是否存在,再用 -f 判断是否为普通文件,用 -d 判断是否为目录,示例:

bash

运行

复制代码
if [ -e "$path" ]; then
    if [ -f "$path" ]; then echo "是文件"; fi
    if [ -d "$path" ]; then echo "是目录"; fi
else
    echo "路径不存在"
fi

5. 问:Shell 算术判断支持小数吗?如果不支持,怎么解决?

答:不支持,Shell 算术判断只处理整数。比较小数可以用 bc 命令,示例(判断 3.5 是否大于 2.8):

bash

运行

复制代码
if [ $(echo "3.5 > 2.8" | bc) -eq 1 ]; then
    echo "3.5 大于 2.8"
fi

六、复习记忆口诀(快速记核心)

  1. 字符串:等不等(=!=),空非空(-z-n),变量要套双引号;
  2. 算术数:eq/ne 判等否,gt/lt 比大小,别用 >< 用符号;
  3. 文件测:e 判存在,f 判文件,d 判目录,rwx 判权限;
  4. 语法上:[] 两边留空格,分号换行都能写。

总结

  1. Shell if 条件判断核心分三类:字符串(文本)、算术(数字)、文件测试(路径),操作符不能混用;
  2. 语法细节([] 空格、变量双引号)是面试必考点,一定要记牢;
  3. 避坑点(不用 >/<、先判存在再判类型)能体现你的实操经验,面试加分。
相关推荐
心.c2 小时前
Vue3+Node.js实现文件上传并发控制与安全防线 进阶篇
前端·javascript·vue.js·安全·node.js
pas1362 小时前
36-mini-vue nextTick
前端·javascript·vue.js
梅梅绵绵冰2 小时前
springboot初步1
java·前端·spring boot
星辰_mya2 小时前
nginx之待续-没写完
前端
GISer_Jing3 小时前
大语言模型Agent入门指南
前端·数据库·人工智能
运筹vivo@3 小时前
BUUCTF: [极客大挑战 2019]Upload
前端·web安全·php·ctf
qq_12498707533 小时前
基于Spring Boot的长春美食推荐管理系统的设计与实现(源码+论文+部署+安装)
java·前端·spring boot·后端·毕业设计·美食·计算机毕业设计
运筹vivo@3 小时前
攻防世界: easyupload
前端·web安全·php·ctf
UI设计兰亭妙微3 小时前
兰亭妙微:以HTML前端、UI/交互/图标设计赋能数字孪生与大屏设计新标杆
前端·ui·用户体验设计