模块S13 可移植性与规范篇号S13-01 / 42预计阅读50 分钟主线Bash对照 POSIXsh文章目录本篇目标30 秒速览正文1. 先看清 shebang2. POSIX sh 与 Bash 关系够用理解3. 总对照表语法4. 条件表达式最常踩坑4.1 [ vs [[4.2 整数比较4.3 组合条件5. 参数展开6. 循环与控制7. 函数与作用域8. set 选项9. 读脚本红旗列表10. 何时选 sh、何时选 Bash11. 从 Bash 迁到 sh 的替换思路预览12. 与 ShellCheck读脚本检查清单练习判断题改错题对照题下一篇预告本篇目标建立POSIX sh与Bash的语法对照读到#!/bin/sh却满篇[[、(( ))时能判断风险写脚本时能决定坚持 POSIX还是明确 Bash。本篇是对照表编写清单与command/printf在S13-02。30 秒速览POSIX sh各系统上的/bin/sh可能是dash、bash 的 posix 模式等语法最小公共子集。Bash扩展多——[[、(( ))、数组、{1..10}、pipefail、进程替换等。shebang 与内容要一致#!/bin/sh里不要写 Bash 专用语法。可移植优先[、test、$(( ))、printf、.、getopts。本专栏主线是Bash需要sh时查本篇 S13-02。正文1. 先看清 shebang第一行含义#!/bin/sh用系统sh解释不保证是 Bash#!/usr/bin/env bash明确要Bash专栏推荐#!/bin/bashBash路径写死部分系统无此路径读脚本第一问第一行承诺的运行时是否支持下文里的 Bash 语法#!/bin/shif[[-f$f]];then# 错[[ 不是 POSIX常见情况作者本机/bin/sh指向 bash脚本在dash/Alpine busybox sh上直接报错。2. POSIX sh 与 Bash 关系够用理解POSIX标准文档规定 shell 语法子集。实现Linux 上sh常为dashDebian/Ubuntu或bash --posixmacOS 曾长期不同。Bash超集bash script.sh可跑 Bash 语法sh script.sh只能跑 POSIX加实现少量扩展。专栏策略教学用 Bash交付若要求sh按本篇改写法。3. 总对照表语法特性POSIX shBash专栏条件if [ ]✅✅S05-01[[ ]]❌✅S05-03正则~❌✅[[ ]]S05-03模式 *.log❌✅[[ ]]S05-03算术测试(( ))❌✅S05-04[ $n -eq 10 ]✅✅S05-01let部分✅S05-04function f()❌f()可以✅S08-01local❌✅S08-02数组arr( )❌✅S03-04${arr[]}❌✅S03-04${var:0:5}子串❌✅S03-02${var:-def}部分POSIX 有子集✅S03-02for i in {1..10}❌✅S07-01for (( ))❌✅S07-01select❌✅S08-04getopts✅✅S08-04source❌用.✅ 同.S08-03$(cmd)✅✅S09-03进程替换( )❌✅S09-04set -o pipefail❌✅S01-04、S09-02PIPESTATUS❌✅S09-02重定向❌✅S09-01here-string❌✅S09-01[[内—✅S05-03echo -e不可移植常用用printfS13-02read -r✅✅S07-02trapEXIT部分✅S11-01flock非 POSIX 命令常见S11-02timeout非 POSIX 命令GNUS11-024. 条件表达式最常踩坑4.1[vs[[# POSIXif[$a$b];thenif[-f$file];then# Bash onlyif[[$a$b]];thenif[[$f*.log]];then4.2 整数比较# POSIX[$n-eq10]# Bash脚本内常用但 sh 不行((n10))4.3 组合条件# POSIX两个 [ 或 -a不推荐 -a[$ax][$by]# Bash[[$ax$by]]5. 参数展开写法POSIX shBash$1$✅✅${var:-def}✅✅${var:def}✅✅${#var}✅✅${var#prefix}❌✅${var/pat/rep}❌✅数组${a[]}❌✅写#!/bin/sh时避免S03-02里 Bash 专有展开S13-02 给替代写法。6. 循环与控制# POSIXforfin$;dowhile[$n-lt10];don$((n1))done# Bash onlyforiin{1..10};dofor((i0;i10;i));dobreak/continuePOSIX 均有。7. 函数与作用域# POSIX 函数myfunc(){echo$1}# Bash 扩展myfunc(){localx1declare-in0}export -fBash非 POSIX。8.set选项选项POSIX shBashset -e✅✅set -u部分✅set -o pipefail❌✅set -x✅✅#!/bin/shset -euo pipefail在dash上-u通常可用pipefail不可用ShellCheckSC3043。9. 读脚本红旗列表见到#!/bin/sh或dash却出现[[(( )){1..10}source应用.数组、${var//x/y}( )select→要么 shebang 错了要么脚本在部分系统会挂。应改为#!/usr/bin/env bash或改写成 POSIXS13-02。见到#!/usr/bin/env bash可合理使用专栏全部 Bash 特性。10. 何时选 sh、何时选 Bash选POSIX sh选Bash嵌入式/极简 rootfs开发机、CI、团队统一 Bash明确要求dash兼容需要数组、[[、pipefail被sh调用的极小片段复杂逻辑、运维工具专栏默认不要假设「sh 就是 bash」。11. 从 Bash 迁到 sh 的替换思路预览BashPOSIX 倾向[[ -f f ]][ -f f ](( $# 1 ))[ $# -lt 1 ][[ $x *.log ]]case $x in *.log)${s#pre}sed/expr笨但可移植source f. fpipefail拆开管道或显式查$?细节与command/printf在S13-02。12. 与 ShellCheckshellcheck-sshscript.sh# 按 POSIX 扫shellcheck-sbashscript.sh# 按 Bash 扫shebang 与-s一致。见S12-02。读脚本检查清单第一行shebang与文内语法是否一致#!/bin/sh下是否误用[[、数组、pipefail需要模式匹配时sh 是否改用case整数比较是否用-eq而非(( ))在 sh 脚本里是否用printf代替echo -eS13-02练习判断题#!/bin/sh保证脚本在所有 Unix 上由 Bash 执行。[[是 Bash 扩展不是 POSIX。getopts可在 POSIX sh 脚本中使用。set -o pipefail在所有/bin/sh实现上都可用。读脚本时 shebang 与语法冲突应优先信语法还是信 shebang——应让它们一致。参考答案错。对。对。错。应一致冲突时按更严格的 sh 理解或改 shebang。改错题下面脚本声称兼容sh请指出 Bash 专有写法#!/bin/shset-euopipefailfiles($)[[${#files[]}-lt1]]exit2source./lib.shforiin{1..3};do[[$i~^[0-9]$]]run$idone参考答案数组files( )、${#files[]}[[、~、模式pipefaildash sh 不行source→.{1..10}应改为#!/usr/bin/env bash或逐项 POSIX 化S13-02。对照题将下列 Bash 改为POSIX[/test风格不要求可运行表达即可[[ -f $f -r $f ]](( $# 1 ))[[ $x *.log ]]参考答案[ -f $f ] [ -r $f ][ $# -ge 1 ]case $x in *.log) ... ;; esac或[ -f $x ]等按语义改写下一篇预告S13-02《可移植脚本编写清单与command/printf》— 实战 checklist、command -v、避免echo陷阱完成 S13 模块。