Mac下Zsh脚本中sed修改package.json失效问题求助
问题原因分析
- 变量未被解析:你用单引号包裹sed的替换表达式,导致
${scripts}和${newScripts}被sed当作字面量字符串,而非shell变量的实际值。package.json里不存在这个字面量内容,所以替换操作无效果。 - JSON多行结构不兼容sed默认行为:sed默认逐行处理文本,但package.json中的
scripts块是多行嵌套格式,简单的s/旧内容/新内容/无法匹配跨多行的完整scripts结构,就算变量被解析也可能匹配失败。
修正方案
方案一:修复sed命令(适合简单场景)
步骤1:改用双引号解析变量
把sed命令的单引号替换为双引号,让shell先解析变量值:
sed -i '' "s/${scripts}/${newScripts}/" "$packpath"
步骤2:处理多行匹配(关键)
由于scripts是多行结构,需要启用sed的多行匹配功能(Mac用的BSD sed需加-E启用扩展正则)。示例如下:
# 提取原scripts块内容 original_scripts=$(grep -A 100 '"scripts": {' "$packpath" | grep -B 100 '},' | head -n -1) # 构建包含predeploy和deploy的新scripts内容 new_scripts=$(echo "$original_scripts" | sed '$ s/^ / "predeploy": "npm run build",\n /; $ s/^ / "deploy": "gh-pages -d build"\n /') # 替换原scripts块 sed -i '' -E "/\"scripts\": \{/,/\}/c\\ \"scripts\": {\\ $new_scripts\\ }" "$packpath"
方案二:用jq处理JSON(推荐,更稳定)
jq是专门处理JSON的工具,能完美适配JSON的格式规则,避免sed处理JSON时的各种问题:
- 先安装jq(未安装的话执行):
brew install jq
- 修改ghdeploy函数为:
ghdeploy() { packpath="./package.json" if [ ! -f "$packpath" ]; then echo "当前目录未找到package.json" return 1 fi # 添加或覆盖predeploy、deploy脚本 jq '.scripts += {"predeploy": "npm run build", "deploy": "gh-pages -d build"}' "$packpath" > temp.json && mv temp.json "$packpath" echo "已成功为package.json添加predeploy和deploy脚本" }
优势:
- 自动维护JSON的语法结构(逗号、缩进、换行等),不会破坏文件格式
- 支持覆盖已存在的同名脚本,避免重复添加
- 无需编写复杂正则,逻辑更清晰可靠
额外注意事项
- 若坚持使用sed,必须确保
scripts变量能精确匹配package.json中scripts块的完整内容(包括空格、换行),否则匹配失败就无法替换 - Mac的BSD sed与Linux的GNU sed语法存在差异,注意
-i参数的使用:Mac需要-i '',GNU sed直接用-i即可
内容的提问来源于stack exchange,提问作者James Newton
相关产品推荐
相关产品推荐

