2015-02-05 70 views
0

我有一些像Foo.<Whatever>.$(Something)定義的格式的一些字符串,我想將它們分成幾部分,並讓每個部分自動分配給一個變量。模式匹配與提取找到的子字符串變量

我曾經寫過類似bash/shell pipe命令選項'<'的C#類和運算符重載。用法是像

ParseExpression ex = pex("item1") > ".<" > pex("item2") > ">.$(" > pex("item3") > ")"; 
ParseResult r = new ParseResult(ex, "Foo.<Whatever>.$(Something)"); 

ParseResult然後有一個解釋的鑰匙物品1通過項目3設定爲指定字符串中找到的字符串。方法pex生成了一些可以與>操作符一起使用的對象,最終生成一個構成ParseExpression的ParseExpressionParts鏈。

我目前沒有手頭的代碼,在我開始從頭開始編寫代碼之前,我想我最好問問是否有人已經完成併發布了它。

+1

這應該可以通過一個簡單的正則表達式來實現,這是沿着^(\ w +)\的方向。 <(\w+)> \。\ $ \((\ w +)\)$',這會產生Foo,Whatever和Something作爲組1,2和3.不需要解析器。 – Heinzi 2015-02-05 14:48:33

+0

有沒有一些漂亮的庫,可以更容易地構造正則表達式表達式:'Regex r = RegexBuilder.AnyChar()。FollowedBy('<')。AnyChar()。FollowedBy('>')... '? – David 2015-02-06 11:59:51

+0

我建議「咬緊牙關」,學習正則表達式語法。是的,這是一個非常晦澀的語言,但(與其他晦澀難懂的語言相反),它非常有用,並且(或多或少)標準化。這是一次性的投資,從長遠來看,這將是回報。 – Heinzi 2015-02-06 12:26:56

回答

1

我開始與Heinzi的建議,並最終想出了下面的代碼:

const string tokenPrefix = "px"; 
const string tokenSuffix = "sx"; 
const string tokenVar = "var"; 

string r = string.Format(@"(?<{0}>.*)\$\((?<{1}>.*)\)(?<{2}>.*)", 
         tokenPrefix, tokenVar, tokenSuffix); 
Regex regex = new Regex(r); 
Match match = regex.Match("Foo$(Something)Else"); 

if (match.Success) 
{ 
    string prefix = match.Groups[tokenPrefix].Value; // = "Foo" 
    string suffix = match.Groups[tokenSuffix].Value; // = "Something" 
    string variable = match.Groups[tokenVar].Value; // = "Else" 
} 

跟一個collegue關於這一點,我被告知後考慮在我的模式使用增加時使用名爲"Sprache"(這是正則表達式和ANTLR相似的工具集之間的東西)的C#解析器coonstruction庫,並且我希望具有更好的可維護性。

1

解析表達式使我想起像parser combinators像Parsec和FParsec(用於F#)。語法將會有多複雜?事實上,它可以通過一個帶有組的正則表達式來處理。

如果您想使用解析器組合器創建更復雜的語法,您可以使用FParsec,這是一個以F#爲目標的着名解析器組合器。一般來說,像F#這樣的函數式語言在這種情況下被大量使用。 CSharp-monad是一個針對C#的解析器組合器。這個項目雖然不是很活躍。

您還可以使用全面的解析器生成器,如ANTLR 4。 ASP.NET MVC使用ANTLR來分析Razor語法視圖。 ANTLR 4創建了一個分析樹,並允許您使用Visitor或Listener來處理它,這與DOM或SAX處理類似。只要遇到元素,監聽器就會調用您的代碼(例如,開頭<,內容等等),而訪問者在完成的樹上工作。

ANTLR的Visual Studio擴展將爲您的語法生成解析器類以及基礎Visitor和Listener類。基於NetBeans的ANTLRWorks IDE使創建和測試語法非常簡單。

您例如一個粗略的語法是:

format: tag '.' '<' category '>' '.' '$' '(' value ')'; 
tag  : ID; 
category : ID; 
value : ID; 

ID  :[A-Z0-9]+; 

或者你可以這樣定義FOO : 'FOO'關鍵字,對你的語法特殊的意義。訪客或聽衆可以處理標籤,例如格式化字符串,對數值執行操作等。

沒有硬性規定。就個人而言,我使用正則表達式來處理更簡單的情況,例如處理相對簡單的日誌文件和更復雜的情況下的ANTLR,例如屏幕抓取大型機數據。我沒有看過解析器組合器,因爲我從來沒有時間去熟悉F#。他們將是非常方便的,雖然來處理一些亂七八糟log4net的日誌文件

相關問題