2009-01-15 86 views
14

我編寫用正則表達式解析文本的程序。正則表達式應該從用戶處獲得。我希望爲用戶輸入使用glob語法,並在內部將glob字符串轉換爲正則表達式。例如:從glob表達式創建正則表達式

"foo.? bar*" 

應轉換爲

"^.*foo\.\w\bar\w+.*" 

不知怎的,我需要從字符串逃避所有有意義的字符,然後我需要更換水珠*和?具有適當的正則表達式語法的字符。最簡單的方法是什麼?

+0

正則表達式看起來有點奇怪。像:「^。* foo」可以寫成「foo」。我認爲這個通用的明星會轉化爲正則表達式「*?」。搜索空間在哪裏?和\ bar匹配以「ar」開頭的單詞。 – PEZ 2009-01-15 09:17:46

回答

-2
+15

只是發佈一個鏈接作爲答案不是一個好的答案。如果鏈接在未來中斷,該怎麼辦?我們鼓勵您在答案中引用鏈接,這樣如果鏈接中斷,答案仍然存在堆棧溢出。 – 2013-07-21 21:29:33

1

我寫我自己的函數,用C++和boost ::正則表達式

std::string glob_to_regex(std::string val) 
{ 
    boost::trim(val); 
    const char* expression = "(\\*)|(\\?)|([[:blank:]])|(\\.|\\+|\\^|\\$|\\[|\\]|\\(|\\)|\\{|\\}|\\\\)"; 
    const char* format = "(?1\\\\w+)(?2\\.)(?3\\\\s*)(?4\\\\$&)"; 
    std::stringstream final; 
    final << "^.*"; 
    std::ostream_iterator<char, char> oi(final); 
    boost::regex re; 
    re.assign(expression); 
    boost::regex_replace(oi, val.begin(), val.end(), re, format, boost::match_default | boost::format_all); 
    final << ".*" << std::ends; 
    return final.str(); 
} 

它看起來像一切工作正常

2

我不知道我完全瞭解要求。如果我假設用戶想要在他們的搜索匹配中找到文本「條目」,那麼我認爲這種蠻橫的方式將作爲一個開始。

首先逃避一切正則表達式的意義。然後使用非正則表達式替換替換(現在已轉義)的glob字符並構建正則表達式。像這樣在Python:

regexp = re.escape(search_string).replace(r'\?', '.').replace(r'\*', '.*?') 

對於問題的搜索字符串,這將構建一個正則表達式,看起來像這樣(生):

foo\..\ bar.*? 

用於在Python代碼片段:

search = "foo.? bar*" 
text1 = 'foo bar' 
text2 = 'gazonk foo.c bar.m m.bar' 

searcher = re.compile(re.escape(s).replace(r'\?', '.').replace(r'\*', '.*?')) 

for text in (text1, text2): 
    if searcher.search(text): 
    print 'Match: "%s"' % text 

產品:

Match: "gazonk foo.c bar.m m.bar" 

請注意,如果您檢查匹配對象,則可以找到有關匹配的更多信息並用於突出顯示或其他內容。

當然,可能還有更多,但它應該是一個開始。

+0

這就對了,但你需要alsough替換()| \ []和其他有意義的字符在字母串 – Lazin 2009-01-15 10:59:29

43

不需要不完整或不可靠的黑客。這裏有一個python包含的函數

>>> import fnmatch 
>>> fnmatch.translate('*.foo') 
'.*\\.foo$' 
>>> fnmatch.translate('[a-z]*.txt') 
'[a-z].*\\.txt$' 
1

jPaq的RegExp.fromWildExp函數做了類似這樣的事情。從是網站的前面頁的示例進行的以下:

// Find a first substring that starts with a capital "C" and ends with a 
// lower case "n". 
alert("Where in the world is Carmen Sandiego?".findPattern("C*n")); 

// Finds two words (first name and last name), flips their order, and places 
// a comma between them. 
alert("Christopher West".replacePattern("(<*>) (<*>)", "p", "$2, $1")); 

// Finds the first number that is at least three numbers long. 
alert("2 to the 64th is 18446744073709551616.".findPattern("#{3,}", "ol"));