正则表达式:为什么文字 'bob' 在这些行中不匹配?

Regex: Why isn't the literal 'bob' matched in these lines?

如何更新此正则表达式,使其即使行中不存在 bob 也能匹配? (Python).

^(AllowUsers.*) (\bbob\b) ?(.*)$

我天真的想法是在捕获组 2 上添加一个“0 或 1”量词:(\bbob\b)?,但是当我这样做时,除了末尾没有其他地方有 bob 的行更长的比赛:

### 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

我对正则表达式(第 2 组 ?)的理解是:

这是正则表达式 101 link:https://regex101.com/r/39zNfm/1

如果我删除 (\bbob\b) 上的“0 或 1”量词,那么我会匹配其中包含 bob 的所有行,并且我会得到正确的捕获组,但是 我不再匹配其中没有 bob 的行。

我误会了什么?

所需的匹配和捕获行为

例如:

背景

我正在使用 lineinfile 内置函数编写 Ansible 任务。此任务的目标是将用户添加到 /etc/ssh/sshd_configAllowUsers 指令。

使用lineinfile,使用的正则表达式必须匹配修改前后的行,这样才能保持幂等性。

最后,任务看起来像:

- 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: " {{ user }} "   # might have to fiddle with literal space. eg: "{{ user}}"
    backrefs: yes
  loop: { ssh_users }
  loop_control:
    loop_var: user

如果我对你的问题的理解正确,那么这样做就可以了:
^(AllowUsers.*)?(\bbob\b)|(.*)
查看 regex demo 并检查右侧的说明 - 键是 ?|("alternate")

编辑:
更新后的测试用例不匹配任何不以“AllowUsers”开头的内容,并且需要将其匹配为第 1 组,这是一个解决方案:
^(AllowUsers )(?>(.*)?(\bbob\b)(.*)|(.*))$
regex demo

编辑#2:
发布上述编辑后,注意到 OP 请求更改为三组捕获。所以模式进一步细化如下:
^(?|(AllowUsers.+?(?=\bbob\b))(\bbob\b)(.*)|(AllowUsers .*))$
regex demo of Edit #2