Home > Enterprise >  Need to generate a list based on one item name and number of items
Need to generate a list based on one item name and number of items

Time:01-17

I have two variables:

name: "abc232323defg10"
cycle: "4"

I need to generate a list:

list:
  - abc232323defg10
  - abc232323defg9
  - abc232323defg8
  - abc232323defg7

where:

abc232323defg9 = abc232323defg(10-(cycle-3)),
abc232323defg8 = abc232323defg(10-(cycle-2)), 
abc232323defg7 = abc232323defg(10-(cycle-1))

The variable "cycle" is the same as the number of items in the list, and I already have item where last 2 characters are the "largest number" (that is number 10 in the example). So other items should have last two characters subtracted from this "largest number" (with increments for each cycle). Cycle is never bigger then "largest number", but can be equal. Order in the list is not relevant.

PS last two characters can be any number or even combination of one letter (a-z,A-Z) and one number. So it can be t1, or e9, or 88... that is why I think I need regex.

Any idea?

CodePudding user response:

An example playbook with

---
- hosts: localhost
  become: false
  gather_facts: false

  vars:
    NAME: "ABCD1000"
    COUNTER: 4

  tasks:

  - name: Example loop

    debug:
      msg: "{{ NAME | regex_search('[0-9] ') | int - item | int }}"
    loop: "{{ range(1, COUNTER  1) }}"

will result into an output of

TASK [Example loop] **********
ok: [localhost] => (item=1) =>
  msg: '999'
ok: [localhost] => (item=2) =>
  msg: '998'
ok: [localhost] => (item=3) =>
  msg: '997'
ok: [localhost] => (item=4) =>
  msg: '996'

The filter

NAME | regex_search('[0-9] ') | int

will just extract the digits from the name and cast it to integer for further processing.

The part

- item | int

will subtract the loop counter from the gathered integer value.

Then you just need to adjust the start and end values, as well the order if necessary.

Further Q&A and Documenation


In respect to your comments and update and to catch up the last numeric character from your input value, you may test with

  - name: Last numeric characters
    debug:
      msg: "{{ NAME | regex_search('(\\d )(?!.*\\d)') }}"

resulting for example input values of abcd123t1, abc123e9, or abc12378 into an output of 1, 9 or 12378.

Similar Q&A


You may also consider to have a look how big your input values are since the loop

TASK [Last numeric character] **********
ok: [localhost] =>
  msg: '1'

TASK [Example loop] **********
ok: [localhost] => (item=1) =>
  msg: '0'
ok: [localhost] => (item=2) =>
  msg: '-1'
ok: [localhost] => (item=3) =>
  msg: '-2'
ok: [localhost] => (item=4) =>
  msg: '-3'

could end up with negative values.

CodePudding user response:

Given the variables

  _name: "abc232323defg10"
  cycle: "4"

Declare the variables prefix and index by splitting _name

  prefix: "{{ _name|regex_replace('^(. ?)(\\d )$', '\\1') }}"
  index: "{{ _name|regex_replace('^(. ?)(\\d )$', '\\2') }}"

give

  prefix: abc232323defg
  index: 10

Declare the list indexes

 indexes: "{{ query('sequence', params) }}"
 params: "start={{ index|int }} end={{ index|int - cycle|int   1 }} stride=-1"

give

  indexes: ['10', '9', '8', '7']

Finally, create product of the prefix and indexes, and join them

  names: "{{ [prefix]|product(indexes)|map('join')|list }}"

gives the expected result

  names:
    - abc232323defg10
    - abc232323defg9
    - abc232323defg8
    - abc232323defg7

Example of a complete playbook for testing

- hosts: localhost

  vars:

    _name: "abc232323defg10"
    cycle: "4"

    prefix: "{{ _name|regex_replace('^(. ?)(\\d )$', '\\1') }}"
    index: "{{ _name|regex_replace('^(. ?)(\\d )$', '\\2') }}"
    indexes: "{{ query('sequence', params) }}"
    params: "start={{ index|int }} end={{ index|int - cycle|int   1 }} stride=-1"
    names: "{{ [prefix]|product(indexes)|map('join')|list }}"

  tasks:

    - debug:
        msg: |
          prefix: {{ prefix }}
          index: {{ index }}
          indexes: {{ indexes }}
          names:
            {{ names|to_nice_yaml|indent(2) }}
  • Related