我有以下字符串:
>>> repr(s)
" NBCUniversal\\n63 VOLGAFILM, INC VOLGAFILMINC\\n64 Video Service Corp
我希望在\\n
之前匹配字符串 - 在空格字符之前的所有内容。输出应为:
['NBCUniversal', 'VOLGAFILMINC']
这是我到目前为止所做的:
re.findall(r'[^s].+\\n\d{1,2}', s)
这个正确的正则表达式是什么?
答案 0 :(得分:1)
如果您想在文字 \n
之前立即找到所有字母组,re.findall
是合适的。您可以通过以下方式获得所需的结果:
>>> import re
>>> s = " NBCUniversal\\n63 VOLGAFILM, INC VOLGAFILMINC\\n64 Video Service Corp "
>>> re.findall(r'(?i)[a-z]+(?=\\n)', s)
['NBCUniversal', 'VOLGAFILMINC']
老答案:
re.findall
不是合适的方法,因为您只需要一个结果(即一对字符串)。这里re.search
方法更合适:
>>> import re
>>> s = " NBCUniversal\\n63 VOLGAFILM, INC VOLGAFILMINC\\n64 Video Service Corp "
>>> res = re.search(r'^(?i)[^a-z\\]*([a-z]+)\\n[^a-z\\]*([a-z]+)', s)
>>> res.groups()
('NBCUniversal', 'VOLGAFILM')
注意:我假设第一个单词与文字 \n
之间没有其他字符,但如果不是这样,则可以添加{{1}在模式中的[^a-z\\]*
之前。
答案 1 :(得分:1)
如果你想修复现有的代码而不是替换它,那么你就是在正确的轨道上,你只是遇到了一些小问题。
让我们从你的模式开始:
>>> re.findall(r'[^s].+\\n\d{1,2}', s)
[' NBCUniversal\\n63 VOLGAFILM, INC VOLGAFILMINC\\n64']
第一个问题是,.+
会匹配它可以的所有内容,一直到最后一个\\n\d{1,2}
,而不仅仅是下一个\\n\d{1,2}
。要解决此问题,请添加?
以使其不贪婪:
>>> re.findall(r'[^s].+?\\n\d{1,2}', s)
[' NBCUniversal\\n63', ' VOLGAFILM, INC VOLGAFILMINC\\n64']
请注意,我们现在应该有两个字符串。问题是,这些字符串不仅具有与.+?
匹配的任何字符串,它们具有与整个模式匹配的任何字符串。要解决此问题,请将要捕获的部分包裹在()
中以使其成为捕获组:
>>> re.findall(r'[^s](.+?)\\n\d{1,2}', s)
[' NBCUniversal', ' VOLGAFILM, INC VOLGAFILMINC']
那更好,但它在左端还有一堆额外的东西。为什么?好吧,你在[^s]
之后捕获了所有内容。这意味着除了s
之外的任何字符。你几乎肯定意味着[\s]
,意思是空白类中的任何字符。 (注意\s
已经是空白类,所以[\s]
,意味着由空白类组成的类是不必要的。)这样更好,但仍然只能匹配一个空格,而不是所有空间。并且它将匹配最早的空间,它仍然可以留下.+?
匹配的东西,而不是最新的。因此,如果你想吸掉所有多余的空间,你需要重复它:
re.findall(r'\s+(.+?)\\n\d{1,2}', s)
['NBCUniversal', 'VOLGAFILM, INC VOLGAFILMINC']
越来越近了......但.+?
匹配任何,包括VOLGAFILM
和VOLGAFILMINC
之间的空格,再次\s+
正在进行匹配它可以的第一批空格,让.+?
匹配之后的所有内容。
您可以使用前缀,但有一个更简单的解决方案。如果您不想在捕获组中使用空格,只需使用\S
捕获一系列非空格而不是任何内容:
re.findall(r'\s+(\S+?)\\n\d{1,2}', s)
['NBCUniversal', 'VOLGAFILMINC']
请注意,一旦你完成了这项工作,\s+
就不会再做任何事了,所以让我们放弃它:
re.findall(r'(\S+?)\\n\d{1,2}', s)
['NBCUniversal', 'VOLGAFILMINC']
我显然已经做出了一些适用于您的样本输入的假设,但对于实际数据可能不正确。例如,如果您有一个类似Weyland-Yutani\\n…
的字符串,我假设您需要Weyland-Yutani
,而不仅仅是Yutani
。如果您有不同的规则,例如只有字母,只需将括号中的部分更改为符合该规则的内容,例如(\w+?)
或([A-Za-z]+?)
。
答案 2 :(得分:0)
假设输入实际上有序列\n
(反斜杠后跟字母'n')而不是换行符,这将起作用:
>>> re.findall(r'(\S+)\\n', s)
['NBCUniversal', 'VOLGAFILMINC']
如果字符串实际包含换行符,则在正则表达式中将\\n
替换为\n
。