[Solved] Formatting regexp in a condition of an automation

EDIT (TL;DR): finally working with (automations.yaml, Home Assistant v0.103.5) due to requiring multi-line YAML caused by double quotes confusing the YAML parser (see detailed explanation below):

- alias: Disable Pi-Hole
  trigger:
    platform: state
    entity_id: input_select.pihole_time
  condition: # valid if in the format 'HH:MM:SS'
    - condition: template
      value_template: >
        {{ states('input_select.pihole_time')|regex_match("^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$", ignorecase=FALSE) }}
  action:
    service: pi_hole.disable
    data_template:
      duration: "{{ states('input_select.pihole_time') }}"

Hi all,

I have the following automation:

- alias: Disable Pi-Hole
  trigger:
    platform: state
    entity_id: input_select.pihole_time
  condition: # valid if in the format 'HH:MM:SS'
    - condition: template
      value_template: "{{ states('input_select.pihole_time')|regex_match('^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$', ignorecase=FALSE) }}"
  action:
    service: pi_hole.disable
    data_template:
      duration: "{{ states('input_select.pihole_time') }}"

but I am getting the errors:

Error loading /config/configuration.yaml: while scanning a double-quoted scalar
  in "/config/automations.yaml", line 298, column 23
found unknown escape character 'd'
  in "/config/automations.yaml", line 298, column 92

Line 298 is the line with the regular expression. What’s wrong here? :see_no_evil: Please note that the expression works correctly in the template editor. Also tried double quotes with no luck. :confused:

Thanks!

1 Like

I was just reading this:

So you want:

  condition: # valid if in the format 'HH:MM:SS'
    - condition: template
      value_template: >
        {{ states('input_select.pihole_time')|regex_match("^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$", ignorecase=FALSE) }}

If you did not use a multi line template you would have problems with the open and close double quotes.

e.g. this:

value_template: "{{ states('input_select.pihole_time')|regex_match("
                ^---------------- matching pair -------------------^

I think the problem is that, when entered on one line and having the overall string quoted with double-quote characters, YAML string parsing is seeing/consuming the escape characters (so they’re not left in the string being given to regex_match. Also YAML string parsing doesn’t seem to like \d. Neither of which is an issue in the template editor, or for multi-line YAML.) So another solution is to escape the escape characters (very common in other systems, and why Python invented “raw” strings – r"abc\d123" as opposed to having to enter "abc\\d123"):

      value_template: "{{ states('input_select.pihole_time')|regex_match('^(?:(?:([01]?\\d|2[0-3]):)?([0-5]?\\d):)?([0-5]?\\d)$', ignorecase=FALSE) }}"

Or simply swap single and double quote characters (because apparently YAML doesn’t process special characters in single quoted strings like it does with double quoted strings):

      value_template: '{{ states("input_select.pihole_time")|regex_match("^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$", ignorecase=FALSE) }}'

Multi-line YAML should would with the single quote characters, too:

      value_template: >
        {{ states('input_select.pihole_time')|regex_match('^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$', ignorecase=FALSE) }}
2 Likes

Thank you very much @tom_l and @pnbruckner, also for the good explanation, makes perfectly sense especially from the perspective of a YAML parser! :grin:

Multi-line strings did the trick here. Sometimes, YAML (parsing) is simply a pain in the a**… :see_no_evil:

Note @pnbruckner that I also tried raw strings but that did not work, too.

Sorry, I was only mentioning that as an example of how Python added a feature to avoid the need to escape escape characters. I didn’t mean to imply you could do that in YAML.

In any case, glad you got it working.

1 Like

Ahh, okay thanks for clarifying! I knew about that feature (raw strings) in Python that’s why I also applied it to the YAML code (which I know now, didn’t make sense). :see_no_evil::+1: