You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible Playbook中sed命令unterminated `s`错误的排查与修复

问题:Ansible中执行sed合并行命令报错

我有一个存储任务API代码及对应状态的文件,状态行位于API代码行的下一行,需要将每两行配对合并。在Shell中使用sed 'N;s/[\n]//'命令可正常运行,但在Ansible Playbook中执行时出现错误:sed: -e expression #1, char 4: unterminated s' command`。

相关信息

输入文件示例(api_file)

"id": "3b96db40-507e-4dd8-b2fd-e0e237fb928f",
"enabled": true,
...

期望输出

"id": "3b96db40-507e-4dd8-b2fd-e0e237fb928f","enabled": true,
...

Playbook片段

- name: retrieve the IDs from the integration APIs
  shell: "cat api_file | sed 's/^ *//'  > merged_api_file"

错误输出

TASK [retrieve the IDs from the integration APIs] *************************************************************************************************************************
Friday 07 July 2023  16:12:23 +0000 (0:00:00.805)       0:00:04.707 *********** 
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "/usr/bin/cat /mnt/stl-server-actions/opsgenie/disable/opsgenie-integrations-2023-07-06-22-15-46.conf | egrep \"\"id\"|\"enabled\"\" | sed 's/^ *//' | sed -e 'N;s/\n//' > /mnt/stl-server-actions/opsgenie/disable/opsgenie-integrations-id-2023-07-06-22-15-46.conf", "delta": "0:00:00.005732", "end": "2023-07-07 16:12:23.294963", "msg": "non-zero return code", "rc": 1, "start": "2023-07-07 16:12:23.289231", "stderr": "sed: -e expression #1, char 4: unterminated `s' command", "stderr_lines": ["sed: -e expression #1, char 4: unterminated `s' command"], "stdout": "", "stdout_lines": []}

问题原因

Ansible的YAML解析器会处理字符串中的转义字符,导致sed命令里的\n被提前解析,实际传递给sed的命令变成了N;s//,缺少替换目标内容,因此触发“unterminated s' command”错误。同时从错误输出的cmd字段可见,egrep部分的引号也存在转义异常,但核心报错由sed`的换行符转义问题导致。

修正方案

方案1:用单引号包裹整个shell命令,避免YAML转义

将shell命令用单引号包裹,内部单引号用两个单引号转义(符合YAML单引号转义规则),确保命令原样传递给shell:

- name: retrieve the IDs from the integration APIs
  shell: 'cat api_file | sed ''s/^ *//'' | sed ''N;s/\n//'' > merged_api_file'

方案2:使用YAML块标量(|)定义命令,保留原始格式

通过|定义多行shell命令,无需额外转义即可保留原始命令格式:

- name: retrieve the IDs from the integration APIs
  shell: |
    cat api_file | sed 's/^ *//' | sed 'N;s/\n//' > merged_api_file

方案3:合并sed命令,减少管道(可选优化)

将两个sed命令合并为一个,提升执行效率:

- name: retrieve the IDs from the integration APIs
  shell: |
    sed -e 's/^ *//' -e 'N;s/\n//' api_file > merged_api_file

或更简洁的写法:

- name: retrieve the IDs from the integration APIs
  shell: 'sed ''s/^ *//;N;s/\n//'' api_file > merged_api_file'

验证

修正后的Playbook执行时,sed命令会正确接收N;s/\n//参数,实现每两行合并为一行并去除行首空格的效果,得到期望输出。

内容的提问来源于stack exchange,提问作者Philip Shangguan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:31:57