2016-03-19 100 views
1

我有一個C++函數名平面文件和聲明的一部分是這樣的:Python的正則表達式 - 非貪婪匹配不起作用

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_name1function_name3,它不會做非貪婪匹配的OU。的fn_name.group() tput的是

:NameSpace2::ClassName1::function_name1 

我有三個問題:

  1. 我希望只是字符串「function_name1」從第1行中提取,但非貪婪的比賽似乎並沒有工作。爲什麼?
  2. 爲什麼第3行不被提取?
  3. 如何使用單個正則表達式從所有行中獲取函數名稱?

請幫忙。

+0

你是否知道're.match'匹配從字符串的開頭開始?您的任何字符串都不以冒號開頭。你嘗試過're.search'嗎? –

+0

延遲匹配不影響正則表達式開始匹配的位置 - 它隻影響匹配的結束 –

回答

2

這至少工作得很好,你的榜樣:

^(?:\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'] 

外賣:如果你可以用貪婪的匹配做,做它與貪婪的匹配。


注意\w不正確一個C標識符,但寫下匹配那些技術上正確的字符類之外的問題。找到並使用正確的字符集而不是\w

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
  1. 我希望只是字符串「function_name1」從第1行中提取,但非貪婪的比賽似乎並沒有工作。爲什麼?

這是你的正則表達式":(.*?)\(?"

的結果我想你的正則表達式是「懶得」。它將只匹配:,因爲(.*?)代表匹配任何字符「越少越好」然後正則表達式引擎選擇匹配零字符。因爲?只意味着「可選」它將不會匹配,直到\(?

  1. 爲什麼第3行沒有被提取?

因爲我測試了你的正則表達式。它根本不工作,不僅僅是第三條線。

  1. 如何使用單個正則表達式從所有行中獲取函數名?

你可以從這個小例子

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

(?:\:\:|void\s+)代表了什麼,你的領導函數名和(?:\(|$)代表了什麼,跟着你函數名開始。

請注意,function_name4假設由於缺乏模式而被明確聲明。

見:DEMO

0

我一直在試圖捕捉從 「N ---- 1」 「N富巴ň---- 1 ---- 2」,當類似的事情之前難倒。添加領先的。*給出了期望的結果。

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