簡體   English   中英

在格式化字符串中提取一些值

[英]Extract some values in formatted string

我想以字符串格式檢索值,如下所示:

public var any:int = 0;
public var anyId:Number = 2;
public var theEnd:Vector.<uint>;
public var test:Boolean = false;
public var others1:Vector.<int>;
public var firstValue:CustomType;
public var field2:Boolean = false;
public var secondValue:String = "";
public var isWorks:Boolean = false;

我想在自定義類Property中存儲字段名稱,類型和值:

public class Property
{
    public string Name { get; set; }
    public string Type { get; set; }
    public string Value { get; set; }
}

並使用Regex表達式獲取這些值。

我能怎么做 ?

謝謝

編輯:我試過這個,但我不知道如何進一步使用vectors..etc

    /public var ([a-zA-Z0-9]*):([a-zA-Z0-9]*)( = \"?([a-zA-Z0-9]*)\"?)?;/g

好的,發布我的基於正則表達式的答案。

你的正則表達式 - /public var ([a-zA-Z0-9]*):([a-zA-Z0-9]*)( = \\"?([a-zA-Z0-9]*)\\"?)?;/g ?; /public var ([a-zA-Z0-9]*):([a-zA-Z0-9]*)( = \\"?([a-zA-Z0-9]*)\\"?)?;/g - 包含正則表達式分隔符,它們在C#中不受支持,因此被視為文字符號。 您需要將其刪除和改性劑g因為以獲得多個匹配在C# Regex.Matches ,或Regex.MatchwhileMatch.Success / .NextMatch()都可以使用。

我正在使用的正則表達式是(?<=\\s*var\\s*)(?<name>[^=:\\n]+):(?<type>[^;=\\n]+)(?:=(?<value>[^;\\n]+))? 包含換行符號,因為否定字符類可以匹配換行符。

var str = "public var any:int = 0;\r\npublic var anyId:Number = 2;\r\npublic var theEnd:Vector.<uint>;\r\npublic var test:Boolean = false;\r\npublic var others1:Vector.<int>;\r\npublic var firstValue:CustomType;\r\npublic var field2:Boolean = false;\r\npublic var secondValue:String = \"\";\r\npublic var isWorks:Boolean = false;";
var rx = new Regex(@"(?<=\s*var\s*)(?<name>[^=:\n]+):(?<type>[^;=\n]+)(?:=(?<value>[^;\n]+))?");
var coll = rx.Matches(str);
var props = new List<Property>();
foreach (Match m in coll)
    props.Add(new Property(m.Groups["name"].Value,m.Groups["type"].Value, m.Groups["value"].Value));
foreach (var item in props)
    Console.WriteLine("Name = " + item.Name + ", Type = " + item.Type + ", Value = " + item.Value);

或者使用LINQ:

var props = rx.Matches(str)
          .OfType<Match>()
          .Select(m => 
               new Property(m.Groups["name"].Value, 
                   m.Groups["type"].Value, 
                   m.Groups["value"].Value))
          .ToList();

和班級的例子:

public class Property
{
    public string Name { get; set; }
    public string Type { get; set; }
    public string Value { get; set; }
    public Property()
    {}
    public Property(string n, string t, string v)
    {
        this.Name = n;  
        this.Type = t;
        this.Value = v;
    }
}

關於性能的說明

正則表達式不是最快的,但它肯定勝過另一個答案中的正則表達式。 這是在regexhero.net上執行的測試:

在此輸入圖像描述

看來,你不想要正則表達式 ; 在您提供的簡單案例中:

  String text =
    @"public var any:int = 0;
      public var anyId:Number = 2;
      public var theEnd:Vector.<uint>;
      public var test:Boolean = false;
      public var others1:Vector.<int>;
      public var firstValue:CustomType;
      public var field2:Boolean = false;";

  List<Property> result = text
    .Split(new Char[] {'\r','\n'}, StringSplitOptions.RemoveEmptyEntries)
    .Select(line => {
       int varIndex = line.IndexOf("var") + "var".Length;
       int columnIndex = line.IndexOf(":") + ":".Length;
       int equalsIndex = line.IndexOf("="); // + "=".Length;
       // '=' can be absent
       equalsIndex = equalsIndex < 0 ? line.Length : equalsIndex + "=".Length;

       return new Property() {
         Name = line.Substring(varIndex, columnIndex - varIndex - 1).Trim(),
         Type = line.Substring(columnIndex, columnIndex - varIndex - 1).Trim(),
         Value = line.Substring(equalsIndex).Trim(' ', ';')
       };
    })
    .ToList();

如果文本可以包含評論和其他人員,例如

  "public (*var is commented out*) var sample: int = 123;;;; // another comment"

你必須實現一個解析器

您可以使用以下模式:

\s*(?<vis>\w+?)\s+var\s+(?<name>\w+?)\s*:\s*(?<type>\S+?)(\s*=\s*(?<value>\S+?))?\s*;

匹配一行中的每個元素。 追加? 在量詞導致非貪婪的匹配之后,這使得模式更加簡單 - 不需要否定所有不需要的類。

值是可選的,因此值組包裝在另一個可選組中(\\s*=\\s*(?<value>\\S+?))?

使用RegexOptions.Multiline選項意味着我們不必擔心意外匹配換行符。

以下示例中的C#6語法不是必需的,但是多行字符串文字和插值字符串可以實現更清晰的代碼。

var input= @"public var any:int = 0;
            public var anyId:Number = 2;
            public var theEnd:Vector.<uint>;
            public var test:Boolean = false;
            public var others1:Vector.<int>;
            public var firstValue:CustomType;
            public var field2:Boolean = false;
            public var secondValue:String = """";
            public var isWorks:Boolean = false;";

var pattern= @"\s*(?<vis>\w+?)\s+var\s+(?<name>\w+?)\s*:\s*(?<type>\S+?)(\s*=\s*(?<value>\S+?))?\s*;"
var regex = new Regex(pattern, RegexOptions.Multiline);
var results=regex.Matches(input);
foreach (Match m in results)
{
    var g = m.Groups;
    Console.WriteLine($"{g["name"],-15} {g["type"],-10} {g["value"],-10}");
}

var properties = (from m in results.OfType<Match>()
                    let g = m.Groups
                    select new Property
                    {
                        Name = g["name"].Value,
                        Type = g.["type"].Value,
                        Value = g["value"].Value
                    })
                    .ToList();

我會考慮使用像ANTLR這樣的解析器生成器,如果我必須解析更復雜的輸入或者有多個模式匹配。 學習如何編寫語法需要一些時間,但是一旦你學會了它,就很容易創建能夠匹配需要非常復雜的正則表達式的輸入的解析器。 空白管理也變得容易多了

在這種情況下,語法可能是這樣的:

property   : visibility var name COLON type (EQUALS value)? SEMICOLON;
visibility : ALPHA+;
var        : ALPHA ALPHA ALPHA;
name       : ALPHANUM+;
type       : (ALPHANUM|DOT|LEFT|RIGHT);
value      : ALPHANUM
           | literal;
literal    : DOUBLE_QUOTE ALPHANUM* DOUBLE_QUOTE;

ALPHANUM   : ALPHA
           | DIGIT;
ALPHA      : [A-Z][a-z];
DIGIT      : [0-9];
...
WS         : [\r\n\s] -> skip;

使用解析器,添加例如注釋SEMICOLONproperty規則中的SEMICOLON之前添加comment一樣簡單,以及與comment模式匹配的新comment規則

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM