为什么此正则表达式在Python中有效,但在Ruby中无效:
/(?<!([0-1\b][0-9]|[2][0-3]))/
很高兴听到一个解释以及如何在Ruby中解决它
编辑带有整行代码:
re.sub(r'(?<!([0-1\b][0-9]|[2][0-3])):(?!([0-5][0-9])((?i)(am)|(pm)|(a\.m)|(p\.m)|(a\.m\.)|(p\.m\.))?\b)' , ':\n' , s)
基本上,我试图在没有冒号的情况下添加'\n'
。
答案 0 :(得分:1)
Ruby正则表达式引擎不允许捕获后面的组。
如果您需要分组,则可以使用非捕获组(?:)
:
[8] pry(main)> /(?<!(:?[0-1\b][0-9]|[2][0-3]))/
SyntaxError: (eval):2: invalid pattern in look-behind: /(?<!(:?[0-1\b][0-9]|[2][0-3]))/
[8] pry(main)> /(?<!(?:[0-1\b][0-9]|[2][0-3]))/
=> /(?<!(?:[0-1\b][0-9]|[2][0-3]))/
(?<!subexp) negative look-behind
Subexp of look-behind must be fixed-width.
But top-level alternatives can be of various lengths.
ex. (?<=a|bc) is OK. (?<=aaa(?:b|cd)) is not allowed.
In negative look-behind, capturing group isn't allowed,
but non-capturing group (?:) is allowed.
从this answer那里学习。
答案 1 :(得分:1)
肯定@mrzasa找出了问题所在。
但是..
猜测您打算用':\ n`
替换非时间冒号
我猜可以这样做。也会修剪一些空白。
(?i)(?<!\b[01][0-9])(?<!\b[2][0-3])([^\S\r\n]*:)[^\S\r\n]*(?![0-5][0-9](?:[ap]\.?m\b\.?)?)
PCRE-https://regex101.com/r/7TxbAJ/1替换$1\n
Python-https://regex101.com/r/w0oqdZ/1替换\1\n
可读版本
(?i)
(?<!
\b [01] [0-9]
)
(?<!
\b [2] [0-3]
)
( # (1 start)
[^\S\r\n]*
:
) # (1 end)
[^\S\r\n]*
(?!
[0-5] [0-9]
(?: [ap] \.? m \b \.? )?
)
答案 2 :(得分:0)
访问到Onigmo regex documentation,否定式后备支持不支持捕获组。尽管在正则表达式引擎中很常见,但并非所有人都将其视为错误,因此您会看到re
和Onigmo正则表达式库中的差异。
现在,对于您的正则表达式来说,它不能正常工作,在Ruby和Python中都无法正常工作:Python和Ruby的正则表达式中的字符类中的\b
与BACKSPACE匹配( \x08
)字符,而不是单词边界。此外,当您在可选的非单词char后面使用单词边界时,如果char出现在字符串中,则必须立即在该非单词char的右侧出现单词char。字边界必须移至m
之前\.?
之后。
当前方法的另一个缺陷是,回退并不是最好排除某些特定上下文(如此处)的方法。例如。您不能在时间数字和am
/ pm
之间计入可变数量的空格。最好匹配您不想触摸的上下文,并匹配并捕获要修改的上下文。因此,我们在这里需要两个主要选择,一个在时间字符串中匹配am
/ pm
,另一个在所有其他上下文中匹配它们。
您的模式也有太多可供选择的选择,可以使用字符类和?
量词进行合并。
\b((?:[01]?[0-9]|2[0-3]):[0-5][0-9]\s*[pa]\.?m\b\.?)
:
\b
-单词边界((?:[01]?[0-9]|2[0-3]):[0-5][0-9]\s*[pa]\.?m\b\.?)
-捕获组1:
(?:[01]?[0-9]|2[0-3])
-可选的0
或1
,然后是任意数字或2
,然后是从0
到3
的数字:[0-5][0-9]
-:
,然后是从00
到59
的数字\s*
-超过0个空格[pa]\.?m\b\.?
-a
或p
,可选点,m
,单词边界,可选点|
-或\b[ap]\.?m\b\.?
-单词边界a
或p
,可选点,m
,单词边界,可选点import re
text = 'am pm P.M. 10:56pm 10:43 a.m.'
rx = r'\b((?:[01]?[0-9]|2[0-3]):[0-5][0-9]\s*[pa]\.?m\b\.?)|\b[ap]\.?m\b\.?'
result = re.sub(rx, lambda x: x.group(1) if x.group(1) else "\n", text, flags=re.I)
text = 'am pm P.M. 10:56pm 10:43 a.m.'
rx = /\b((?:[01]?[0-9]|2[0-3]):[0-5][0-9]\s*[pa]\.?m\b\.?)|\b[ap]\.?m\b\.?/i
result = text.gsub(rx) { $1 || "\n" }
输出:
"\n \n \n 10:56pm 10:43 a.m."