Search code examples
regexansible

How to strip quotes from a variable in Ansible?


I'm trying to get the value of a variable in a file into an Ansible variable so I can use it.

Here's what I've got:

  - name: extract Unique Key
    shell: "grep UNIQUE_KEY ../config.py | cut -d' ' -f 3"
    register: command_output

  - set_fact:
      unique_key: x{{ command_output.stdout | regex_replace("^'", '') | regex_replace('^"', '') | regex_replace("'$", '') | regex_replace('"$', '')  }}

  - set_fact:
      unique_key: "{{ unique_key | regex_replace('^x', '') }}"

  - debug: var=unique_key

This works, but feels kludgy and looks ugly.

I've already tried to add sed to my original shell module, but I couldn't figure out how to get the quotes escaped correctly. I also couldn't figure out how to escape the regex_replace to get it to work in a single variable assignment.

Is there a simpler way to go from this:

"TEST"

or

'TEST'

to this:

TEST

in Ansible? (I'm also really new to Ansible so that's not helping either)

EDIT: After the answer by @Vladimir-Botka which I initially accepted, I found this issue:

If I don't strip the quotes and embed the variable in another variable, it keeps the quotes:

I need to use this value to construct a path:

vars:
  service_location: "/opt/{{ unique_key }}-scheduler-service"

If I don't remove the quotes using my method above, The variable will contain the quotes as in this output of a debug statement:

ok: [fedorasvr1] => {
    "service_location": "/opt/'TEST'-scheduler-service"
}

Solution

  • The short answer is "omit the first and the last character" if the quotes are part of the string

          - set_fact:
              unique_key: command_output.stdout[1:-1]
    

    Internal interpretation is all the same. The quotes control the expansion of the variables. See 7.3.1. Double-Quoted Style and 7.3.2. Single-Quoted Style.

    As an example. The play below

        - hosts: localhost
          vars:
            var1: TEST
            var2: 'TEST'
            var3: "TEST"
          tasks:
            - template:
                src: test.j2
                dest: test
    

    and the template

        shell> cat test.j2
        {{ var1 }}
        {{ var2 }}
        {{ var3 }}
    

    give

        shell> cat test
        TEST
        TEST
        TEST
    

    The quotes, if part of the string, can be removed. As an example the play below

        - hosts: localhost
          vars:
            regex: "[`'\"]"
            replace: ""
            service_location: "/opt/{{ item|regex_replace(regex, replace)
                                       }}-scheduler-service"
          tasks:
            - debug:
                var: service_location
              loop:
                - '`TEST`'
                - '"TEST"'
                - '''TEST'''
                - "'TEST'"
    

    gives

        ok: [localhost] => (item=`TEST`) => 
          item: '`TEST`'
          service_location: /opt/TEST-scheduler-service
        ok: [localhost] => (item="TEST") => 
          item: '"TEST"'
          service_location: /opt/TEST-scheduler-service
        ok: [localhost] => (item='TEST') => 
          item: '''TEST'''
          service_location: /opt/TEST-scheduler-service
        ok: [localhost] => (item='TEST') => 
          item: '''TEST'''
          service_location: /opt/TEST-scheduler-service
    

    It is also possible to use custom filter_plugins/string_filters.py which might be more convenient than complex escape constructs.

    As an example. The play below

        - hosts: localhost
          vars:
            replace: ""
            service_location: "/opt/{{ item.0|string_replace(item.1, replace)
                                       }}-scheduler-service"
          tasks:
            - debug:
                var: service_location
              with_together:
                - - '`TEST`'
                  - '"TEST"'
                  - "'TEST'"
                - - '`'
                  - '"'
                  - "'"
    

    gives

        ok: [localhost] => (item=[u'`TEST`', u'`']) => 
          item:
          - '`TEST`'
          - '`'
          service_location: /opt/TEST-scheduler-service
        ok: [localhost] => (item=[u'"TEST"', u'"']) => 
          item:
          - '"TEST"'
          - '"'
          service_location: /opt/TEST-scheduler-service
        ok: [localhost] => (item=[u"'TEST'", u"'"]) => 
          item:
          - '''TEST'''
          - ''''
          service_location: /opt/TEST-scheduler-service
    

    FWIW, see other examples of filter_plugins.