正则表达式:为什么文字 '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 组 ?
)的理解是:
^(AllowUsers.*)
:匹配以 AllowUsers
开头的行并捕获其后的任何内容(第 1 组),不包括 space。这是贪心。
(\bbob\b)?
:匹配并捕获bob
(第2组),如果存在。我们使用单词边界 (\b
) 这样我们就不会错误匹配,例如 billybob
.
?(.*)$
:匹配可选的 space 并捕获其后的任何内容(第 3 组)。
这是正则表达式 101 link:https://regex101.com/r/39zNfm/1
如果我删除 (\bbob\b)
上的“0 或 1”量词,那么我会匹配其中包含 bob
的所有行,并且我会得到正确的捕获组,但是 我不再匹配其中没有 bob
的行。
我误会了什么?
所需的匹配和捕获行为
- 正则表达式应匹配任何以
AllowUsers
开头的行,无论行中是否存在 bob
。
- 如果
bob
不在行中,则捕获整行。分两组进行:第1组和第3组。如果第3组为空也可以。
- 如果
bob
在行中,则捕获之前(第1组),包括(第2组)和之后(第3组) 的所有内容
例如:
背景
我正在使用 lineinfile
内置函数编写 Ansible 任务。此任务的目标是将用户添加到 /etc/ssh/sshd_config
的 AllowUsers
指令。
使用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
- 这使用 分支重置模式,(?|alternation)。有关这方面的更多信息,请参阅 Use branch reset grouping to number captures in alternations
- 此外,请参阅 match everything up to (but not including) the exact sequence "abc" 以了解
.+?(?=abc)
模式的解释
如何更新此正则表达式,使其即使行中不存在 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 组 ?
)的理解是:
^(AllowUsers.*)
:匹配以AllowUsers
开头的行并捕获其后的任何内容(第 1 组),不包括 space。这是贪心。(\bbob\b)?
:匹配并捕获bob
(第2组),如果存在。我们使用单词边界 (\b
) 这样我们就不会错误匹配,例如billybob
.?(.*)$
:匹配可选的 space 并捕获其后的任何内容(第 3 组)。
这是正则表达式 101 link:https://regex101.com/r/39zNfm/1
如果我删除 (\bbob\b)
上的“0 或 1”量词,那么我会匹配其中包含 bob
的所有行,并且我会得到正确的捕获组,但是 我不再匹配其中没有 bob
的行。
我误会了什么?
所需的匹配和捕获行为
- 正则表达式应匹配任何以
AllowUsers
开头的行,无论行中是否存在bob
。 - 如果
bob
不在行中,则捕获整行。分两组进行:第1组和第3组。如果第3组为空也可以。 - 如果
bob
在行中,则捕获之前(第1组),包括(第2组)和之后(第3组) 的所有内容
例如:
背景
我正在使用 lineinfile
内置函数编写 Ansible 任务。此任务的目标是将用户添加到 /etc/ssh/sshd_config
的 AllowUsers
指令。
使用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
- 这使用 分支重置模式,(?|alternation)。有关这方面的更多信息,请参阅 Use branch reset grouping to number captures in alternations
- 此外,请参阅 match everything up to (but not including) the exact sequence "abc" 以了解
.+?(?=abc)
模式的解释