这感觉就像一个非常简单的问题,但我无法在任何地方找到答案。
(注意:我正在使用Python,但这不重要。)
说我有以下字符串:
s = "foo\nbar\nfood\nfoo"
我只是试图找到一个匹配“foo”两个实例的正则表达式,而不是“食物”,基于“食物”中的“foo”不会立即跟随换行符或字符串的结尾。
这可能是表达我的问题的一种过于复杂的方式,但它提供了一些具体的工作方法。
以下是我尝试过的一些结果(注意:我想要的结果是[foo\n
,foo
]):
foo[\n\Z]
=> ['foo\n'
]
foo(\n\Z)
=> ['\n'
,''
]< =这似乎与换行符和EOS匹配,但不匹配foo
foo($|\n)
=> ['\n'
,''
]
(foo)($|\n)
=> [(foo
,'\n'
),(foo
,''
)]< =几乎就在那里,这是一个可用的计划B,但我想找到完美的解决方案。
我发现唯一有用的是:
foo$|foo\n
=> ['foo\n'
,“'foo']
这对于这样一个简单的例子来说很好,但很容易看出它如何变得难以处理,表达方式更大(是的,这个foo
这个东西代表了我实际上更大的表达式使用)。
有趣的是:我能找到的最接近的问题是这个问题:In regex, match either the end of the string or a specific character
在这里,我可以简单地用\n
代替我的'特定角色'。现在,接受的答案使用正则表达式/(&|\?)list=.*?(&|$)/
。我注意到OP使用的是JavaScript(问题用javascript
标签标记),所以也许JavaScript正则表达式解释器不同,但是当我使用Python中的上述正则表达式中问题中给出的确切字符串时,我得到不好的结果:
>>> findall("(&|\?)list=.*?(&|$)", "index.php?test=1&list=UL")
[('&', '')]
>>> findall("(&|\?)list=.*?(&|$)", "index.php?list=UL&more=1")
[('?', '&')]
所以,我很难过。
答案 0 :(得分:9)
>>> import re
>>> re.findall(r'foo(?:$|\n)', "foo\nbar\nfood\nfoo")
['foo\n', 'foo']
(?:...)
生成non-capturing group。
这是因为(来自re module reference):
re.findall(pattern,string,flags = 0)
返回字符串中pattern的所有非重叠匹配,作为字符串列表。从左到右扫描字符串,并按找到的顺序返回匹配项。 如果模式中存在一个或多个组,则返回组列表;如果模式有多个组,这将是一个元组列表。结果中包含空匹配,除非它们触及另一个匹配的开头。
答案 1 :(得分:2)
您可以使用re.MULTILINE
并在模式中的$
后添加可选的换行符:
s = "foo\nbar\nfood\nfoo"
pattern = re.compile('foo$\n?', re.MULTILINE)
print re.findall(pattern, s)
# -> ['foo\n', 'foo']
答案 2 :(得分:1)
如果您只关心foo
:
In [42]: import re
In [43]: strs="foo\nbar\nfood\nfoo"
In [44]: re.findall(r'\bfoo\b',strs)
Out[44]: ['foo', 'foo']
\b
表示单词边界:
\b
匹配空字符串,但仅匹配单词的开头或结尾。单词被定义为字母数字或下划线的序列 字符,所以单词的结尾用空格或a表示 非字母数字,非下划线字符。请注意,\ b是正式的 定义为\ w和\ W字符之间的边界(或副 反之亦然),或者在\ w和字符串的开头/结尾之间,所以 被认为是字母数字的精确字符集取决于 UNICODE和LOCALE标志的值。例如,r'\ bfoo \ b' 匹配'foo','foo。','(foo)','bar foo baz'但不是'foobar'或 'foo3'。在字符范围内,\ b表示退格 character,与Python的字符串文字兼容。
(Source)