用途
Shell 脚本可移植性(shell-portability)是一份面向 Shell 脚本编写的技能资料,适用于需要让脚本在不同系统、不同 Shell 或不同环境中运行的场景。其核心目标是帮助开发者处理 POSIX 兼容性与平台差异,使脚本具备跨平台能力。
主要能力
Shebang 选择
资料给出两种 shebang 写法:
- Bash 脚本:
#!/usr/bin/env bash,被描述为对 bash 脚本最可移植,可在 Linux、macOS、BSD 上工作。 - POSIX Shell 脚本:
#!/bin/sh,用于最大可移植性,仅使用 POSIX 特性。
Bash 与 POSIX 差异
资料从四个方面对比:
- 数组:Bash 可用
declare -a items=("one" "two" "three")与for item in "${items[@]}";POSIX 则使用位置参数或空格分隔字符串,如set -- one two three配合for item in "$@"。 - Test 语法:Bash 使用扩展 test
[[ "$var" == "value" ]];POSIX 使用基础 test[ "$var" = "value" ]。 - 字符串操作:Bash 支持正则匹配
[[ "$input" =~ ^[0-9]+$ ]];POSIX 使用case或外部工具判断,例如case "$input" in *[!0-9]*|'') echo "not numeric" ;; *) echo "numeric" ;; esac。 - 算术:Bash 使用算术展开
(( count++ ))与if (( count > 10 ));POSIX 使用count=$((count + 1))与if [ "$count" -gt 10 ]。
平台差异
资料列举了 macOS 与 Linux 的常见差异及可移植写法:
- date 命令:GNU(Linux)使用
date -d "yesterday" +%Y-%m-%d;BSD(macOS)使用date -v-1d +%Y-%m-%d。可移植做法是先通过date --version判断是否为 GNU date,再分别调用。 - sed 差异:GNU sed 使用
sed -i 's/old/new/g' file.txt;BSD sed 需要备份扩展名sed -i '' 's/old/new/g' file.txt。可移植做法是重定向到临时文件再移动,或封装sed_inplace函数,通过sed --version判断后分别调用。 - readlink 差异:GNU readlink 支持
readlink -f /path/to/link;BSD/macOS 默认没有 -f 选项。资料给出resolve_path函数,优先使用 greadlink,其次 realpath,最后回退到cd "$(dirname "$path")" && pwd -P。
环境检测
资料提供三个检测函数:
- 操作系统检测
detect_os:通过uname -s判断 Linux、macOS、Windows(MINGW/CYGWIN/MSYS)、FreeBSD 或 unknown,并据此选择安装命令(如 apt-get install 或 brew install)。 - 架构检测
detect_arch:通过uname -m映射为 amd64、arm64、arm 或 unknown。 - Shell 检测
detect_shell:根据$BASH_VERSION、$ZSH_VERSION判断 bash、zsh 或 sh。
可移植模式
资料给出若干可移植写法:
- 读取文件:
while IFS= read -r line || [ -n "$line" ]; do ... done < "$file",其中|| [ -n "$line" ]用于处理没有结尾换行的文件。 - 临时文件:
make_temp函数优先使用 mktemp,否则回退到/tmp/tmp.$$.$RANDOM。 - 命令存在性检查:
has_command函数使用command -v "$1" >/dev/null 2>&1,并示例在 curl 与 wget 之间选择。 - 字符串包含:
contains函数使用case "$1" in *"$2"*) return 0 ;; *) return 1 ;; esac。
ShellCheck 兼容
资料说明在有意使用非可移植特性时,可用 # shellcheck disable=SC2039 等指令禁用警告,并建议注释说明原因。同时给出测试多种 Shell 时的指令写法,如 # shellcheck shell=bash 或 # shellcheck shell=sh。
使用方式
该技能以参考文档形式提供,使用者在编写 Shell 脚本时按需查阅对应章节,将示例代码或函数模式应用到自己的脚本中。资料未提供安装命令或调用接口。
适用场景
- 需要跨 Linux、macOS、BSD 等平台运行的 Shell 脚本。
- 需要在 bash 与 POSIX sh 之间做兼容取舍的脚本。
- 需要处理 date、sed、readlink 等命令平台差异的脚本。
- 需要在脚本中检测操作系统、架构或当前 Shell 的场景。
- 需要编写可移植的文件读取、临时文件、命令检查等通用逻辑的场景。
限制
资料未说明该技能的运行环境要求、依赖版本、授权方式或收费信息。示例代码仅覆盖资料中列出的差异点,未涵盖所有可能的平台或 Shell 差异。