【无标题】

一、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 环境。

相关推荐
全栈前端老曹20 小时前
【MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离
前端·javascript·数据库·mongodb·架构·nosql·副本集
NCDS程序员21 小时前
v-model: /v-model/ :(v-bind)三者核心区别
前端·javascript·vue.js
夏幻灵21 小时前
CSS三大特性:层叠、继承与优先级解析
前端·css
小杨同学呀呀呀呀21 小时前
Ant Design Vue <a-timeline>时间轴组件失效解决方案
前端·javascript·vue.js·typescript·anti-design-vue
华玥作者1 天前
[特殊字符] VitePress 对接 Algolia AI 问答(DocSearch + AI Search)完整实战(下)
前端·人工智能·ai
Mr Xu_1 天前
告别冗长 switch-case:Vue 项目中基于映射表的优雅路由数据匹配方案
前端·javascript·vue.js
前端摸鱼匠1 天前
Vue 3 的toRefs保持响应性:讲解toRefs在解构响应式对象时的作用
前端·javascript·vue.js·前端框架·ecmascript
lang201509281 天前
JSR-340 :高性能Web开发新标准
java·前端·servlet
好家伙VCC1 天前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
未来之窗软件服务1 天前
未来之窗昭和仙君(六十五)Vue与跨地区多部门开发—东方仙盟练气
前端·javascript·vue.js·仙盟创梦ide·东方仙盟·昭和仙君