【无标题】

一、Shell 编程面试核心知识点梳理(详版・面试适配)

1.程序执行类型(解释型 vs 编译型)

核心定义

类型 执行原理 典型语言 / 文件 核心特点 面试高频问法
解释型 依赖解释器,边解析边执行,无需编译 Shell(.sh)、Python 开发快、跨平台,运行稍慢 "Shell 脚本为什么需要 bash 解释器才能运行?"
编译型 先编译为机器码可执行文件,直接运行 C/C++(.c/.cpp) 运行快,需适配不同系统 "解释型和编译型语言的核心区别?"

面试标准答案

解释型语言(如 Shell)无需提前编译,通过解释器逐行解析执行,开发效率高但运行效率较低;编译型语言需先编译为机器可识别的可执行文件,运行效率高但开发周期长。Shell 脚本属于解释型,必须指定#!/usr/bin/bash声明解释器才能执行。

2.Shell 变量体系(3 类核心)

1. 本地变量

  • 定义var=value(等号无空格),仅当前 Shell / 脚本生效,子进程不可访问。
  • 命名 :习惯小写(如line=10),区分环境变量。
  • 面试考点:"本地变量和环境变量的作用域区别?"→ 本地变量仅当前会话有效,脚本结束即销毁。

2. 环境变量

  • 定义export var=value 导出,全局生效,子进程可继承。
  • 常用示例PATH(命令搜索路径)、HOME(用户家目录)、PS1(命令行提示符)、$$(当前进程号)。
  • 命名:固定大写,系统默认 / 用户导出均可。
  • 面试考点 :"如何让脚本中的变量被子脚本读取?"→ 用export导出为环境变量。

3. 参数变量(位置参数)

  • 定义:脚本运行时通过命令行传入的参数,系统自动赋值。
  • 核心变量
    • $0:脚本名;$1-$9:第 1-9 个参数;${10}:第 10 个参数(需大括号);
    • $#:参数总数;$*/$@:所有参数(前者整体,后者独立)。
  • 面试考点 :"写脚本接收 2 个参数,计算两数之和"→ 基础写法:echo $(( $1 + $2 ))

3.if 条件判断(3 类核心场景)

通用语法(必考细节)

复制代码
if [ 条件 ]; then  # [ ] 前后必须加空格,; 可换行为then
  命令
elif [ 条件 ]; then
  命令
else
  命令
fi

1. 字符串判断(处理文本 / 输入)

操作符 含义 示例 避坑点
= 相等 [ "$str" = "hello" ] 变量必须套双引号,= 加空格
!= 不相等 [ "$str" != "exit" ] 空变量不加引号会语法报错
-z 为空 [ -z "$str" ] 判断用户是否未输入内容
-n 非空 [ -n "$str" ] 验证配置项是否填写

2. 算术判断(处理数字比较)

操作符 含义 示例 避坑点
-eq 等于 [ $num -eq 10 ] 禁用 ><(重定向符号)
-ne 不等于 [ $num -ne 5 ] 仅支持整数,小数需用 bc
-gt 大于 [ $num -gt 60 ] $score > 60会创建空文件
-ge 大于等于 [ $num -ge 18 ] -
-lt 小于 [ $num -lt 100 ] -
-le 小于等于 [ $num -le 50 ] -

3. 文件测试(处理路径 / 权限)

操作符 含义 示例 面试高频场景
-e 路径存在 [ -e "$path" ] 先判存在,再判类型 / 权限
-f 普通文件 [ -f "test.sh" ] 判断是否为脚本 / 文本文件
-d 目录 [ -d "logs" ] 判断备份目录是否存在
-r 可读 [ -r "$file" ] 校验读取日志权限
-w 可写 [ -w "$file" ] 校验写入配置权限
-x 可执行 [ -x "test.sh" ] 校验脚本执行权限

面试高频题

问:"如何判断一个路径是文件且可执行?"答:if [ -f "$path" ] && [ -x "$path" ]; then echo "可执行文件"; fi

4.循环结构(3 类核心循环)

1. for 循环(遍历 / 固定次数)

  • 基础写法for i in 1 2 3; do echo $i; done
  • 范围遍历for i in {1..10}; do ...(生成 1-10)
  • 面试考点 :"遍历当前目录所有.sh 文件,添加执行权限"→ for file in *.sh; do chmod +x $file; done

2. while 循环(条件为真循环)

  • 计数循环

    复制代码
    i=0
    while [ "$i" -lt 10 ]; do
      echo $i
      i=$((i+1))  # 现代写法,替代老式expr $i + 1
    done
  • 无限循环while true; do echo hello; sleep 1; done(等价while [ : ]; do ...

  • 面试考点 :"写无限循环,输出当前时间,每 5 秒一次"→ 核心:while true; do date; sleep 5; done

3. until 循环(条件为假循环,与 while 相反)

  • 基础写法

    复制代码
    i=0
    until [ "$i" -ge 10 ]; do  # i≥10时停止
      echo $i
      i=$((i+1))
    done
  • 面试考点:"while 和 until 的区别?"→ while 条件为真执行,until 条件为假执行。

5.面试高频避坑点(加分项)

  1. 变量引号:字符串 / 路径变量必须套双引号,防止空值 / 空格导致语法错误;
  2. 算术运算$((i+1)) 效率高于expr,小数比较用bc(如echo "3.5>2.8" | bc);
  3. 循环退出 :无限循环可通过break(退出循环)、continue(跳过本次)、Ctrl+C终止;
  4. 语法空格[ ]/(( )) 前后、操作符两边必须加空格,否则报错。

6.核心总结(面试速记)

  1. 执行类型:解释型(Shell)靠解释器,编译型(C)先编译后运行;
  2. 变量体系:本地(局部)、环境(全局)、参数(外部传入),export 导出环境变量;
  3. 条件判断:字符串(=/-z)、算术(-gt/-eq)、文件(-f/-d),[] 必加空格;
  4. 循环结构:for 遍历、while 条件循环(支持无限)、until 反向循环,优先用 $(()) 做算术。

5.case 语句:多分支匹配的高效写法

1. 核心作用

  • 替代复杂的 if-elif-else 多分支判断,让代码更简洁、易读。
  • 适合处理固定选项匹配的场景(如用户输入选择、命令参数判断)。

2. 语法规则(面试必记)

复制代码
case "$变量" in
    模式1|模式2)
        命令1
        命令2
        ;;  # 双分号表示当前分支结束
    模式3)
        命令3
        ;;
    *)  # 默认分支,匹配所有未命中的情况
        默认命令
        ;;
esac  # case 倒写作为结束标记

语法细节

  • 变量建议用双引号包裹(如 "$line"),防止空值或空格导致语法错误。
  • 模式支持管道符 | 表示 "或" 关系(如 yes|y 表示匹配 yesy)。
  • *) 是默认分支,必须放在最后,匹配所有未被前面模式命中的情况。
  • 每个分支必须以 ;; 结尾,否则会报错。

3. 结合你的代码示例

复制代码
while true
do
    echo "input:"
    read line
    case "$line" in
        yes|y ) echo "this is yes";;
        no|n ) echo "this is no";;
        end) break;;  # 输入end时退出循环
        *) echo "***";;  # 输入其他内容时输出***
    esac
done
  • 运行逻辑 :无限循环等待用户输入,根据输入内容匹配不同分支:
    1. 输入 yesy → 输出 this is yes
    2. 输入 non → 输出 this is no
    3. 输入 end → 执行 break 退出整个循环
    4. 输入其他内容 → 输出 ***

4. 面试高频考点

  • caseif-elif-else 有什么区别?→ case 更适合处理固定值的多分支匹配,代码更简洁;if-elif-else 适合复杂的条件判断(如范围、逻辑组合)。
  • case 中的 *) 有什么作用?→ :是默认分支,当所有前面的模式都不匹配时执行,避免遗漏场景。
  • :为什么每个分支结尾要用 ;;?→ ;; 是 Shell 规定的分支结束标记,用来分隔不同的模式分支,防止命令串到下一个分支。

6.Shell 函数:代码复用与模块化

1. 核心作用

  • 将重复代码封装成函数,实现代码复用,提高脚本的可维护性。
  • 让脚本逻辑更清晰,便于调试和扩展。

2. 语法规则(面试必记)

复制代码
# 定义函数
函数名() {
    # 函数体(可以使用参数变量 $1、$2...)
    命令
    return 返回值  # 可选,返回值范围0-255(默认0表示成功)
}

# 调用函数
函数名 参数1 参数2

语法细节

  • 函数定义时,() 内不需要写参数列表,参数通过 $1$2$# 等位置变量获取。
  • return 用于返回函数执行状态(0-255),若需返回数值结果,建议用 echo 输出,再通过捕获输出获取(如 result=$(函数名 参数))。
  • 函数内的 $# 表示函数接收的参数个数,而非脚本的参数个数。

3. 结合你的代码示例

示例 1:my_add 加法函数
复制代码
my_add() {
    if [ "$#" -ne 2 ]  # 判断参数个数是否为2
    then
        return 0  # 参数错误时返回0
    fi
    val=`expr $1 + $2`  # 计算两个参数的和
    return $val  # 返回计算结果(注意:返回值不能超过255)
}

# 调用函数
my_add 2 3
echo "返回值=$?"  # $? 是上一个命令的退出状态,这里获取函数的return值

⚠️ 注意 :Shell 函数的 return 值范围是 0-255,若计算结果超过 255 会溢出。如需返回任意数值,建议用 echo 输出:

复制代码
my_add() {
    if [ "$#" -ne 2 ]; then echo 0; return; fi
    echo $(($1 + $2))  # 用echo输出结果
}

result=$(my_add 2 3)  # 捕获函数输出
echo "结果=$result"  # 输出:结果=5
示例 2:fun 函数(演示参数传递)
复制代码
fun() {
    echo "fun run"
    echo "fun: argc=$#"  # 函数参数个数
    echo "fun: \$0=$0"    # 脚本名(不是函数名)
    echo "fun: \$1=$1"    # 第一个函数参数
    echo "fun: \$2=$2"    # 第二个函数参数
}

# 调用函数
fun hello world
  • 运行输出

    plaintext

    复制代码
    fun run
    fun: argc=2
    fun: $0=脚本名.sh
    fun: $1=hello
    fun: $2=world

4. 面试高频考点

  • :Shell 函数如何传递参数?→ :调用函数时直接跟参数,函数内部通过 $1$2$# 等位置变量获取。
  • :Shell 函数的 returnecho 有什么区别?→ return 用于返回执行状态(0-255),echo 用于返回具体结果(适合数值、字符串等)。
  • :为什么 my_add 2 3 后直接 echo $val 为空?→ :函数内的 val 是本地变量,函数执行结束后会销毁。如需获取函数内的变量,需用 echo 输出或全局变量(不推荐)。
  • :Shell 函数和 C 语言函数有什么区别?→ :Shell 函数是解释执行的,参数通过位置变量传递,返回值是状态码;C 语言函数是编译执行的,参数类型固定,返回值可以是任意类型。

三、复习速记清单(面试前快速过)

case 语句

  • 语法:case ... in ... esac,分支用 ;; 结尾。
  • 场景:多选项匹配,替代复杂 if-elif
  • 必记:*) 是默认分支,变量加双引号,模式支持 | 或。

Shell 函数

  • 定义:函数名() { ... },参数用 $1$2 获取。
  • 返回:return 传状态(0-255),echo 传结果。
  • 调用:函数名 参数1 参数2,用 $() 捕获输出。

5.Shell 脚本执行与传参 面试核心速记


一、脚本执行的两种方式

1. 直接执行(./a.sh

  • 原理:启动一个新的 Shell 解释器子进程来执行脚本。
  • 特点:脚本里定义的本地变量不会影响当前 Shell 环境,执行结束后子进程销毁,变量随之消失。
  • 面试考法:问 "直接执行脚本和 source 脚本有什么区别?" → 答:直接执行会创建子进程,而 source 在当前进程执行。

2. 用 .source 执行(. ./a.sh / source ./a.sh

  • 原理:在当前 Shell 解释器进程中直接执行脚本,不会创建子进程。
  • 特点:脚本里的变量、函数等会直接加载到当前 Shell 环境,执行后依然可用。
  • 典型场景 :加载配置文件(如 .bashrc),让配置立即生效。
  • 面试考法 :问 "如何让脚本里的环境变量在当前 Shell 生效?" → 答:用 source. 执行脚本。

二、脚本传参的两种方式

1. 命令行参数传递

  • 用法 :执行脚本时直接跟参数,如 ./a.sh hello world
  • 获取方式 :脚本内部通过位置变量获取:$1(第一个参数)、$2(第二个参数)、$#(参数总数)。
  • 典型场景 :动态传递临时参数,如 ./backup.sh /data 7(备份目录 + 保留天数)。
  • 面试考法 :问 "脚本如何接收命令行参数?" → 答:用 $1$2 等位置变量。

2. 环境变量传递

  • 用法
    • 临时生效:MYSTR=hello ./a.sh(仅当前脚本执行时可见)
    • 全局生效:export MYSTR=hello(当前 Shell 及所有子进程可见)
  • 特点 :环境变量可以被子进程继承,适合传递全局配置(如 PATHHOME)。
  • 面试考法 :问 "如何让环境变量在子脚本中生效?" → 答:用 export 导出,或执行脚本时临时赋值。

三、面试核心对比

对比项 直接执行 ./a.sh . ./a.sh / source ./a.sh
进程 新建子进程执行 当前进程执行
变量影响 不影响当前 Shell 直接修改当前 Shell 环境
适用场景 独立脚本运行 加载配置、共享函数 / 变量

四、高频问答速记

  1. :为什么直接执行脚本需要 chmod +x 权限,而 source 不需要?→ :直接执行需要脚本本身有可执行权限,source 只是读取脚本内容在当前进程执行,不需要可执行权限。

  2. :脚本执行时,./a.sh $MYSTRMYSTR=hello ./a.sh 有什么区别?→ :前者是把 MYSTR 的值作为命令行参数传递,后者是临时设置环境变量让脚本读取。

  3. :如何让脚本里的函数在当前 Shell 中调用?→ :用 source. 执行脚本,函数会加载到当前 Shell 环境。

相关推荐
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 基于HTML5的购物网站的设计与实现为例,包含答辩的问题和答案
前端·html·html5
梦6502 小时前
CSS 元素垂直水平居中的 8 种方法
前端·css
We་ct3 小时前
LeetCode 68. 文本左右对齐:贪心算法的两种实现与深度解析
前端·算法·leetcode·typescript
ShoreKiten3 小时前
ctfshow-web316
运维·服务器·前端
小白啥时候能进阶成功3 小时前
webcodecs配置codec和description
chrome
前端 贾公子3 小时前
release-it 使用指南
前端·javascript
莫生灬灬3 小时前
VueMultiBrowser 5.0 开源 - 基于 Vue3 + CEF 的多浏览器管理器
chrome·开源·c#·自动化·多开·cef3
全栈技术负责人3 小时前
前端团队 AI Core Workflow:从心法到落地
前端·人工智能·状态模式
前端 贾公子4 小时前
深入浅出 CSS 属性:pointer-events: none
前端·css