Python正则表达式 - 非贪婪的匹配不起作用

时间:2016-03-19 13:35:13

标签: python regex python-2.7 non-greedy

我有一个带有一个C ++函数名的平面文件,其部分声明如下:

virtual void NameSpace1::NameSpace2::ClassName1::function_name1(int arg1) const
void function_name2
void NameSpace2::NameSpace4::ClassName2::function_name3
function_name4

我试图通过使用以下行来单独提取函数名称:

fn_name = re.match(":(.*?)\(?", lines)

我可以理解为什么function_name2function_name4不匹配(因为没有前导:。但即使对于function_name1和{{1}我也看到了},它不进行非贪婪的匹配。function_name3的输出是

fn_name.group()

我有三个问题:

  1. 我只期待字符串" :NameSpace2::ClassName1::function_name1 "要从第1行中提取,但非贪婪的匹配似乎不起作用。为什么?
  2. 为什么第3行没有被提取?
  3. 如何使用单个正则表达式从所有行获取函数名称?
  4. 请帮忙。

4 个答案:

答案 0 :(得分:3)

1)始终使用r" "字符串表示正则表达式。

2)

  

我试图通过使用以下行来单独提取函数名称:

fn_name = re.match(":(.*?)\(?", lines)
     

fn_name.group()的输出是

:NameSpace2::ClassName1::function_name1

我没有看到:

import re

line = "virtual void NameSpace1::NameSpace2::ClassName1::function_name1(int arg1) const"

fn_name = re.search(r":(.*?)\(?", line)
print(fn_name.group())

--output:--
:

无论如何,如果你想看看非贪婪是如何运作的,请看这段代码:

import re

line = "N----1----2"

greedy_pattern = r"""
    N
    .*
    \d
"""

match_obj = re.search(greedy_pattern, line, flags=re.X)
print(match_obj.group())

non_greedy_pattern = r"""
    N
    .*?
    \d
"""
match_obj = re.search(non_greedy_pattern, line, flags=re.X)
print(match_obj.group())

--output:--
N----1----2
N----1

非贪婪的版本要求所有匹配.*的字符直到遇到的第一个数字,而贪婪的版本将尝试找到.*的最长匹配,然后是数字。

3)警告!没有正则表达式区域!

func_names = [
"virtual void NameSpace1::NameSpace2::ClassName1::function_name1(int arg1) const",
"void function_name2",
"void NameSpace2::NameSpace4::ClassName2::function_name3",
"function_name4",
]

for func_name in func_names:
    name = func_name.rsplit("::", 1)[-1]

    pieces = name.rsplit(" ", 1)

    if pieces[-1] == "const":
        name = pieces[-2]
    else:
        name = pieces[-1]

    name = name.split('(', 1)[0]
    print(name)

--output:--
function_name1
function_name2
function_name3
function_name4

答案 1 :(得分:3)

这很有效,至少以你的例子为准:

^(?:\w+ +)*(?:\w+::)*(\w+)

即,在Python代码中:

import re

function_name = re.compile(r'^(?:\w+ +)*(?:\w+::)*(\w+)', re.MULTILINE)
matches = function_name.findall(your_txt)

# -> ['function_name1', 'function_name2', 'function_name3', 'function_name4']

外卖:如果你能用贪婪的匹配来做,那就用贪婪的匹配来做。

请注意,对于C标识符,\w 不正确,但写下与此相匹配的技术上正确的字符类除了问题之外。查找并使用正确的字符集,而不是\w

答案 2 :(得分:1)

  
      
  1. 我希望从第1行中提取字符串“function_name1”,但非贪婪的匹配似乎不起作用。为什么?
  2.   

这是您的正则表达式":(.*?)\(?"

的结果

我认为你的正则表达是“Too Lazy”。它仅匹配:,因为(.*?)代表匹配任何字符“尽可能少”然后正则表达式引擎选择匹配零字符。它会在您预期的\(?之前匹配,因为?仅表示“可选”

  
      
  1. 为什么第3行没有被提取?
  2.   

我测试了你的正则表达式。它根本不起作用,不仅仅是第三行。

  
      
  1. 如何使用单个正则表达式从所有行获取函数名称?
  2.   

你可以从这个最小的例子开始

(?:\:\:|void\s+)(\w+)(?:\(|$)|(function_name4)

(?:\:\:|void\s+)代表任何领导您的函数名称的内容,(?:\(|$)代表任何跟随您的函数名称的内容。

请注意,function_name4假设由于缺少模式而被明确声明。

请参阅:DEMO

答案 3 :(得分:0)

我试图从“N foo bar N ---- 1 ---- 2”中捕获“N ---- 1”时被类似的东西所困扰。添加一个前导。*给出了所需的结果。

import re
line = "N foo bar N----1----2"
match_obj = re.search(r'(N.*?\d)', line)
print(match_obj.group(1)) 

match_obj = re.search(r'.*(N.*?\d)', line)
print(match_obj.group(1))

--output:--
N foo bar N----1
N----1