Ansible regular expression to match a string and extract the line

18,377

You may use regex_findall with multiline=True:

(?m)^\S+\s+INPUT\b.*

See the regex demo. Details:

  • ^ - start a line since (?m) is used
  • \S+ - 1+ non-whitespace chars
  • \s+ - 1+ whitespaces
  • INPUT\b - INPUT as a whole word
  • .* - the rest of the line.

In the code:

target: "{{ input | regex_findall('^\\S+\\s+INPUT\\b.*', multiline=True)}}"
Share:
18,377
Knightfox
Author by

Knightfox

Updated on June 15, 2022

Comments

  • Knightfox
    Knightfox almost 2 years

    I'm trying to find a string after 1 white space in a line, if it exists then extract the complete line and store in a different variable. I'm using ansible and regular expression. If the string exists in any other place then it should not be matched.

    I tried to use regex_match and select but got error.

      vars:
        input : "{{ lookup('template', '{{ file }}') }}"
        target: "{{ input | regex_search('^(?=.*\b INPUT\b)(?:\S+){1}(\S*.*)')}}"
    

    Error always appear at same place "(?:\S+)".

    ERROR! Syntax Error while loading YAML.
      found unknown escape character 'S'
    
    The offending line appears to be:
    
        input : "{{ lookup('template', '{{ file }}') }}"
        target: "{{ input | regex_search('^(?=.*\b INPUT\b)(?:\S+){1}(\S*.*)')}}"
    
    ^ here
    
        input : "{{ lookup('template', '{{ file }}') }}"
        target: "{{ input | select('match', '^(?=.*\b INPUT\b)(?:\S+){1}(\S*.*)' | list | first}}"
    
    ^ here
    

    I also tried to include escape character for / but got error as well.

    ERROR! Syntax Error while loading YAML.
      found unknown escape character 'S'
    
    The offending line appears to be:
    
       input : "{{ lookup('template', '{{ file }}') }}"
        target: "{{ input | regex_search('^(?=.*/\b INPUT/\b)(?:/\S){1}(/\S*.*)')}}"
                                                                                    ^ here
    

    My variable file

    -P INPUT ACCEPT
    -A INPUT -s 1.1.1.1/32 -j ACCEPT
    -A INPUT -s 2.2.2.2/32 -j ACCEPT
    -A INPUT -s 3.3.3.3/32 -j ACCEPT
    -A INPUT -j RH-Firewall
    -N RH-Firewall
    -A RH-Firewall -j INPUT
    -A RH-Firewall -p icmp -m icmp --icmp-type 0 -j ACCEPT
    -A RH-Firewall -p icmp -m icmp --icmp-type 3 -j ACCEPT
    -A RH-Firewall-1 -p icmp -m icmp --icmp-type 11 -j ACCEPT
    -A RH-Firewall -p icmp -m icmp --icmp-type 11 -j ACCEPT
    

    target_rule_set should contains first 5 lines only. Same way if I match for RH-Firewall then it should contain lines 6-11.

  • Knightfox
    Knightfox almost 5 years
    Thanks Wiktor. Regex works but (?m) is not iterating over the variable. It stops after the first occurrence of the search string.
  • Wiktor Stribiżew
    Wiktor Stribiżew almost 5 years
    @Knightfox It is not (?m) here to blame. Replace re.search with re.findall.
  • Knightfox
    Knightfox almost 5 years
    regex_findall still not searching multiline. From ansible docs found that we need to add multiline=True. target: "{{ input | regex_findall('^\\S+\\s+INPUT\\b.*', multiline=True) }}"
  • Wiktor Stribiżew
    Wiktor Stribiżew almost 5 years
    @Knightfox Great, adjusted the answer.