用ansible字符串替换/

时间:2019-05-14 09:56:57

标签: ansible yaml jinja2

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

我只是想尽可能简单地通过调试对其进行测试,但是无论我如何尝试,我都无法获得仅将字符替换为字符的预期结果。我认为这可能只是单引号/双引号问题,或者\需要以我不知道的某种方式进行转义。

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"
}

5 个答案:

答案 0 :(得分:0)

我认为您偶然发现了一个涉及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

答案 1 :(得分:0)

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

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

#!/usr/bin/python


def filter_reslash(val):
    return val.replace('/', '\\')


class FilterModule(object):
    filter_map = {
        'reslash': filter_reslash
    }

    def filters(self):
        return self.filter_map

然后您可以像这样编写剧本:

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

可以说这是一种更清洁的解决方案。

答案 2 :(得分:0)

@larsks的解决方案对我来说并不完全有效。我需要使用双斜杠\和后卫字符转义反斜杠,以便使其在Ansible Playbook中正常工作。

这有效:replace('/','\\;') | replace(';', '')

答案 3 :(得分:0)

另一个简单的解决方案是将转义的反斜杠留给ansible本身。这就是我要做的。

- set_fact:
    replacer: '\'

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

答案 4 :(得分:0)

如果要在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 }}"