将字符串中的/by\替换为ansible

将字符串中的/by\替换为ansible,ansible,yaml,jinja2,Ansible,Yaml,Jinja2,我需要替换存储在变量中的字符串中的所有/by\ 我只是尽可能简单地用调试来测试它,但无论我如何尝试,我都没有得到一个字符替换一个字符的预期结果。我认为这可能只是一个单引号/双引号问题,或者可能需要以某种方式转义\我不知道 vars: - SecGroup: '/stuff/foo/thing' tasks: - name: Display modified var debug: msg: "{{ SecGroup | replace('/','\')

我需要替换存储在变量中的字符串中的所有/by\

我只是尽可能简单地用调试来测试它,但无论我如何尝试,我都没有得到一个字符替换一个字符的预期结果。我认为这可能只是一个单引号/双引号问题,或者可能需要以某种方式转义\我不知道

vars:
    - SecGroup: '/stuff/foo/thing'
tasks:
    - name: Display modified var
      debug:
        msg: "{{ SecGroup | replace('/','\') }}"
预期输出:\stuff\foo\thing

具有不同尝试的输出:

- name: Display modified var
      debug:
        msg: "{{ SecGroup | replace('/','\') }}"

TASK [Display modified var] 
ok: [localhost] => {
    "msg": "stufffoothing"
}


- name: Display modified var
      debug:
        msg: "{{ SecGroup | replace('/','\\') }}"

TASK [Display modified var] 
fatal: [localhost]: FAILED! => {"msg": "Unexpected failure during module execution."}


- name: Display modified var
      debug:
        msg: "{{ SecGroup | replace('/','\\\') }}"

TASK [Display modified var] 
fatal: [localhost]: FAILED! => {"msg": "Unexpected failure during module execution."}


- name: Display modified var
      debug:
        msg: "{{ SecGroup | replace('/','\\\\') }}"

TASK [Display modified var] 
ok: [localhost] => {
    "msg": "\\\\stuff\\\\foo\\\\thing"
}
我还试图恢复引用:

- name: Display modified var
      debug:
        msg: '{{ SecGroup | replace("/","\") }}'

TASK [Display modified var]
fatal: [localhost]: FAILED! => {"msg": "Unexpected failure during module execution."}
我无法解释这个的输出

- name: Display modified var
      debug:
        msg: '{{ SecGroup | replace("/","\\") }}'

TASK [Display modified var] 
ok: [localhost] => {
    "msg": "\\\\stuff\\\\foo\\\\thing"
}

我认为您偶然发现了一个边缘案例,涉及YAML转义和Python转义之间的交互。我能够让它工作的唯一方法是引入一个保护字符——这可以确保
\
不是表达式中的最后一个字符,然后我们使用后续的
replace()
过滤器删除它。这里我使用了分号(
),但您可以使用您确定不在
SecGroup
字符串中的任何内容。请注意,您对报价的选择非常重要;使用单引号引用整个字符串将禁止YAML转义:

- name: With guard character
  debug:
    msg: '{{ SecGroup | replace("/","\;") | replace(";", "") }}'
产出:

TASK [With guard character] *******************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "\\stuff\\foo\\thing"
}
这正是您想要的(记住单个
\
在JSON输出中编码为
\\


关于这一点:

- name: Display modified var
      debug:
        msg: '{{ SecGroup | replace("/","\\") }}'

TASK [Display modified var] 
ok: [localhost] => {
    "msg": "\\\\stuff\\\\foo\\\\thing"
}
您正在成功地用两个反斜杠替换
/
。由于反斜杠在JSON输出中必须编码为
\\\
,因此双反斜杠最终将表示为
\\\\\
,因此:

"msg": "\\\\stuff\\\\foo\\\\thing"
表示您实际拥有字符串:

\\stuff\\foo\\thing

我想添加一个替代解决方案:

如果您熟悉Python,那么只需编写一个自定义过滤器模块,就可以避免多层转义。例如,如果要创建具有以下内容的
过滤器插件/reslash.py

#/usr/bin/python
def过滤器刷新(val):
返回val.replace(“/”,“\\”)
类FilterModule(对象):
过滤器映射={
“重新刷新”:筛选器\u重新刷新
}
def过滤器(自):
返回self.filter\u映射
你可以这样写剧本:

---
- hosts: localhost
  gather_facts: false
  vars:
    - SecGroup: '/stuff/foo/thing'
  tasks:
    - debug:
        msg: "{{ SecGroup | reslash }}"

这可以说是一个更干净的解决方案。

由@larsks提出的解决方案并没有像上面所描述的那样完全适用于我。我需要用双斜杠
\
加上守卫字符来避开反斜杠,这样它才能在Ansible剧本中工作


这是有效的:
replace(“/”,“\\;”)| replace(“;”,“)
另一个简单的解决方案是将转义反斜杠留给ansible本身。我会这样做的

- set_fact:
    replacer: '\'

- name: With guard character
  debug:
    msg: '{{ SecGroup | replace("/",replacer)}}'

如果要在windows路径上将1个反斜杠替换为双反斜杠,请使用相同的解决方法

- hosts: localhost
  gather_facts: False
  vars:
    - iis_manager_logdir: 'C:\inetpub\logs\manager-logs'
  tasks:
    - set_fact:
        iis_mng_logs: "{{ iis_manager_logdir | regex_replace('\\\\', '\\\\;') | regex_replace(';', '\\\\') }}"
    - name: Original path
      debug:
        msg: "{{ iis_manager_logdir }}"
    - name: New path
      debug:
        msg: "{{ iis_mng_logs }}"

我真的很惊讶ansible在使用“{SecGroup | replace('/','\')}”时没有抛出错误。在双引号标量中,反斜杠可用于转义(此集合)[.2/spec.html#id2776092]转义字符。如果查看该列表,您会发现单引号无法转义,这使得标量无效,必须转义反斜杠。但ansible可能使用模板生成YAML加载,而不是加载YAML并在加载后扩展标量