How can I updated this regex so that it matches even if bob isn't present in the line? (Python).
^(AllowUsers.*) (\bbob\b) ?(.*)$
My naive thought was to just add a "0 or 1" quantifier on capture group 2: (\bbob\b)?, but when I do that, lines that have bob somewhere other than the end no longer match:
### without "?" on capture group 2
# Match
AllowUsers bob
AllowUsers bob billybob
AllowUsers billybob bob
AllowUsers billybob steve bob eric bobby
AllowUsers billybob bobby steve bob eric
AllowUsers richard bob
AllowUsers richard bob jeremy
AllowUsers bob james richard jeremy
AllowUsers bob jeremy
# no match
AllowUsers james richard jeremy
### With "?" on capture group 2:
# All lines match, but `bob` is not captured unless it's at the end of the line:
AllowUsers bob # `bob` captured
AllowUsers billybob bob # `bob` captured
AllowUsers bob billybob # `bob` not captured
My understanding of the regex (with ? on group 2) is:
^(AllowUsers.*): Match lines that start withAllowUsersand capture that any anything after (group 1), not including the space. This is greedy.(\bbob\b)?: Match and capturebob(group 2), if it exists. We use word boundaries (\b) so that we don't incorrectly match, for example,billybob.?(.*)$: Match an optional space and capture anything thereafter (group 3).
Here's the regex101 link: https://regex101.com/r/39zNfm/1
If I remove the "0 or 1" quantifier on (\bbob\b), then I match all lines that have bob in them and I get the correct capture groups, but I no longer match lines that don't have bob in them.
What am I misunderstanding?
Desired match and capture behavior
- The regex should match any line that starts with
AllowUsers, whether or notbobis present in the line. - If
bobis not in the line, then capture the entire line. Do so in two groups: group 1 and group 3. It's OK if group 3 is empty. - If
bobis in the line, then capture everything before (group 1), including (group 2), and after (group 3)
For example:
Background
I'm writing an Ansible task using the lineinfile builtin. The goal of this task is to add users to the AllowUsers directive of /etc/ssh/sshd_config.
With lineinfile, the regex used must match the line before and after modification so that you maintain idempotence.
In the end, the task would look like:
- name: "Allow {{ user }} to log in via SSH"
lineinfile:
path: '/etc/ssh/sshd_config'
state: present
regexp: "^(AllowUsers.*) (\b{{ user }}\b)?(\w*)$" # not currently workng
line: "\1 {{ user }} \3" # might have to fiddle with literal space. eg: "\1{{ user}}\3"
backrefs: yes
loop: { ssh_users }
loop_control:
loop_var: user
