【问题标题】:Replacing / by \ in a string with ansible用ansible替换字符串中的/
【发布时间】:2019-05-14 09:56:57
【问题描述】:

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

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

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

【问题讨论】:

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

标签: ansible yaml jinja2


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    如果你熟悉 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 }}"
    

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

    【讨论】:

      【解决方案3】:

      @larsks 的解决方案并不完全适合我所描述的。我需要用双斜杠 \ 加上保护字符来转义反斜杠,以便它在 Ansible Playbook 中工作。

      这可行:replace('/','\\;') | replace(';', '')

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-12-21
            • 2021-07-04
            • 2015-05-01
            • 2013-07-09
            • 1970-01-01
            • 2012-04-26
            • 1970-01-01
            • 2023-01-09
            相关资源
            最近更新 更多