Ansible - extract more that 1 line from a specific column

so I have the following :

name: "gitea - list gitea users"
debug:
  var: users_checklist.stdout_lines


TASK [gitea - list gitea users] 

ok: [giteahost] => {

"users_checklist.stdout_lines": [
    
"ID   Username   Email                 IsActive IsAdmin",
    
"4    Superadmin [email protected] true     true",
    
"5      git        [email protected]          true     false"

What I want exactly is to extract all Usernames from the second column and till now I only managed to extract the 2nd line from 2nd column using :

name: "gitea - list usernames column"
debug:
  msg: "{{ users_checklist.stdout_lines.1.split().1 }}" 

TASK [gitea - list usernames column] 

ok: [giteahost] => {
"msg": "Superadmin"

.1.split().1 where 1 is actually 2nd line, split column with split() and the remaining 1 pointing to the data after the () space delimiter with the following output:

TASK [gitea - list usernames column] 

ok: [giteahost] => {

"msg": "Superadmin"

I tried putting stdout_lines.[1,2], stdout_lines.[1..2], stdout_lines.[1-2], stdout_lines.*, or stdout_lines.{1,2}, stdout_lines.{1..2} or {1-2} but with no success, please help me out guys!

10X a lot and have a nice day!

Upvotes: 0

Views: 561

Answers (3)

P....
P....

Reputation: 18371

You may use something like the below:

{{  users_checklist.stdout_lines | map('regex_search','^\\d+\\s+\\w+')|select()|map('regex_search', '\\w+$')|list }}

The first map('regex_search') would filter out the first two columns of each row. Then, select() would remove the unmatched rows(header) and the 2nd map('regex_search') would filter the last column of the first two columns meaning the 2nd column.

Example:

---
- name: Sample play
  hosts: localhost
  tasks:

  - debug:
      msg: "{{ foo | map('regex_search','^\\d+\\s+\\w+')|select()|map('regex_search', '\\w+$')|list }}"
    vars:
      foo:
      - ID   Username   Email                 IsActive IsAdmin
      - 4    Superadmin [email protected] true     true
      - 5      git        [email protected]          true     false
      - 1122 foobar     [email protected]          false   true

The above debug would return the following results:

TASK [debug] ***********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "Superadmin",
        "git",
        "foobar"
    ]
}

Upvotes: 1

phanaz
phanaz

Reputation: 1524

You can do this with the following Jinja2 command.

"{{ ( sers_checklist.stdout_lines | map('split') | map(attribute=1) | list )[1:] }}"
  1. first the single entries are splitted: map('split')
  2. for each line the element at position 1 is extracted: map(attribute=1)
  3. the heading is removed: [1:]

Complete example task:

- name: Extract usernames
  debug:
    msg: "{{ ( stdout_lines | map('split') | map(attribute=1) | list )[1:] }}"
  vars:
    stdout_lines:
      - "ID Username Email IsActive IsAdmin"
      - "4 Superadmin [email protected] true true"
      - "5 git [email protected] true false"

Produces the following output (so a list with 2 entries):

TASK [Extract usernames] ***********************************************************************************************
ok: [localhost] => {
    "msg": [
        "Superadmin",
        "git"
    ]
}

Upvotes: 1

Roy Levy
Roy Levy

Reputation: 730

I think a better approach for this would be to format the data using some other tool in your ansible play, maybe run a python script in order to extract what you need (in this case - the user names) to a list (use register in order to extract it) and then iterate over the user names using with_items keyword.

Upvotes: 0

Related Questions