Mac OS下Makefile中Sed命令报错:未终止的替换表达式
问题原因分析
报错有两个核心原因:
- Makefile的特殊字符解析:Makefile中
$是变量引用的特殊符号,原命令里的,$会被Make吃掉$,导致sed实际收到的命令变成s/,\n/,出现「unterminated substitute」语法错误。 - BSD Sed的语法差异:Mac OS自带的是BSD版本Sed,和Linux的GNU Sed语法不同——BSD Sed的替换字符串中无法直接用
\n表示换行,需要特殊处理。
解决方法
方案一:修正转义并适配BSD Sed
修改EXTRACT_JIRA_TICKETS中的Sed命令,把$转义为$$(保留给Sed使用),同时用BSD Sed支持的换行写法:
EXTRACT_JIRA_TICKETS=$(GIT_LOGS) | grep -e '[A-Z]\+-[0-9]\+' -o | sort -u | tr '\n' ',' | sed 's/,$$/\ /' .Phony: check-jira-tickets check-jira-tickets: ## 检查是否有无修复版本的已合并工单 @export JIRA_TICKETS_IDS=$(shell $(EXTRACT_JIRA_TICKETS)); \ echo $${JIRA_TICKETS_IDS};
⚠️ 注意:\后面必须直接换行,不能加任何空格或字符,这样Sed才会识别为换行符。
方案二:简化逻辑,避开换行处理
先用Sed去掉末尾的逗号,再通过echo手动添加换行,避免Sed处理换行的麻烦:
EXTRACT_JIRA_TICKETS=$(GIT_LOGS) | grep -e '[A-Z]\+-[0-9]\+' -o | sort -u | tr '\n' ',' | sed 's/,$$//'; echo .Phony: check-jira-tickets check-jira-tickets: ## 检查是否有无修复版本的已合并工单 @export JIRA_TICKETS_IDS=$(shell $(EXTRACT_JIRA_TICKETS)); \ echo $${JIRA_TICKETS_IDS};
方案三:用Awk替代管道(跨平台友好)
Awk语法跨平台一致,可以直接完成提取、去重、拼接的全流程,彻底避开Sed和Tr的跨平台问题:
EXTRACT_JIRA_TICKETS=$(GIT_LOGS) | awk '/[A-Z]+-[0-9]+/ {tickets[substr($0, RSTART, RLENGTH)]=1} END {sep=""; for(t in tickets) {printf "%s%s", sep, t; sep=","} printf "\n"}' .Phony: check-jira-tickets check-jira-tickets: ## 检查是否有无修复版本的已合并工单 @export JIRA_TICKETS_IDS=$(shell $(EXTRACT_JIRA_TICKETS)); \ echo $${JIRA_TICKETS_IDS};
这个命令通过数组自动去重,拼接时不会产生末尾多余的逗号,直接输出正确格式。
内容的提问来源于stack exchange,提问作者Andrei Lupuleasa
相关产品推荐
相关产品推荐

