none
如何使用正则从含有“类属性代码”的字符串提取出类型,注释,属性名的字符串内容? RRS feed

  • 问题

  • String str="

    //年龄 private int? age; //姓名 private String name;

    "; ……

    有一段字符串,其内容为上述所描述,是实体类属性文件里的内容。想要提取上面的内容,提取到一个实体里,这个实体有property,Comment,type三个字符串属性,组成item,添加到集合里;

    不能简单的使用分割函数split以";"做分割,因为注释可能里面会有";"符号。但每一个提取的界线不得超过property结尾符号";"之后

     若未写Comment,也就是未写//符号,就用property赋值Comment。

    只提取靠近的属性的那一个Comment。

    例如下列情况,注释只提取最近的"名字"

    //private  int age;asd
    
    //名字
    private String name;

    不提取/***/里面的内容

    如何用正则完成?





    • 已编辑 Trian555 2020年1月4日 6:19
    2020年1月2日 2:51

答案

  • 至于注释的选择,你可以再按照你的意图重新编写。

    正则表达式不太会用,我这个效果一般,你多测试测试。健壮性也不够好,你自己多测试测试,仅提供思路以供选择。

    如果其中有其他的修饰符,例如public,static等,你可以改成(private 替换成\S*\s*)

    //?.*|\s*\S*\s*\S*\s*\S*;\s*
    这样的形式,\S*\s*代表一个修饰符,每多一个就加一组

     class Data
        {
            public string Property { get; set; }
            public List<string> Comment { get; set; }
            public string Type { get; set; }
        }
        class Program
        {
            static void Main(string[] args)
            {
                var v = "//名字 \n private int? age;//名字\n private String name;  ";
                v= v.Replace("//", "\n//").Replace(";",";");
                Console.WriteLine(v);
                Regex regex =new Regex(@"//?.*|\s*private\s*\S*\s*\S*;\s*");
                var m= regex.Matches(v);
                List<string> LS = new List<string>();
                List<Data> LD = new List<Data>();
               foreach(Match item in m)
               {
                    var i= item.Value;
                    LS.Add(i);
                    if (!i.Contains("/"))
                    {
                        Data  d= new Data();
                        d.Comment = LS.ToList();
                        d.Comment.RemoveAt(LS.Count - 1);
                        var p = LS.Last();
                        var dp = p.Replace("\n", string.Empty).Replace("\r", string.Empty).Trim().Split(' ');
                        d.Property = dp[0];
                        d.Type = dp[1];
                        LD.Add(d);
                        LS.Clear();
                    }
                    
               }
                Console.WriteLine();
               foreach (var item in LD)
                {
                    string c = string.Empty;
                    foreach (var i in item.Comment)
                        c += $"{i}   ";
                    Console.WriteLine($"type: {item.Type} property : {item.Property} comment :{ c}");
                }
                Console.ReadKey();
            }
        }



    • 已标记为答案 Trian555 2020年5月9日 5:37
    2020年1月5日 8:13

全部回复

  • Hi Trian,

    我想了一下,感觉正则似乎不太好实现这个功能,但是我用反射实现了类似的功能。你看一下是否满足你的要求。

    具体步骤如下:

    1. 自定义一个Attribute。

    2. 用反射获得实体类的所有信息,并给相应的item赋值。

    代码如下:

      class Program
        {
            static void Main(string[] args)
            {
                List<Item> items = new List<Item>();
                MyClass myClass = new MyClass();
                Type type = myClass.GetType();
                FieldInfo[] fieldInfos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
                foreach (var fieldInfo in fieldInfos)
                {
                    Item item = new Item();
                    item.Property = fieldInfo.Name;
    
                    String fullComment = fieldInfo.CustomAttributes.ToList()[0].ToString();
                    string[] strs = fullComment.Split(new char[] { '"' });
                    item.Comment = strs[1] ;
                    item.Type = fieldInfo.FieldType.Name;
                    items.Add(item);
                }
    
                foreach (var item in items)
                {
                    Console.WriteLine(item);
                }
                Console.WriteLine("Press any key to continue...");
                Console.ReadKey();
            }
        }
    
        class MyClass
        {
            [Comment("年龄")]
            private int? age;
    
            [Comment("姓名")]
            private String name;
    
        }
    
        class Item
        {
            public String Property { get; set; }
            public String Comment { get; set; }
            public String Type { get; set; }
            public override string ToString()
            {
                return Property + " " + Type + " " + Comment;
            }
    
        }
        // 自定义一个Attribute
        public class CommentAttribute : Attribute
        {
            private String comment;
            public CommentAttribute() {
                Console.WriteLine(comment);
            }
            public CommentAttribute(string str)
            {
                this.comment = str;
            }
            public String Comment
            {
                get { return this.comment; }
            }
        }

    结果:

    希望能帮到你。

    生活愉快。

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2020年1月2日 9:45
  • Hi Trian,

    我想了一下,感觉正则似乎不太好实现这个功能,但是我用反射实现了类似的功能。你看一下是否满足你的要求。

    具体步骤如下:

    1. 自定义一个Attribute。

    2. 用反射获得实体类的所有信息,并给相应的item赋值。

    代码如下:

      class Program
        {
            static void Main(string[] args)
            {
                List<Item> items = new List<Item>();
                MyClass myClass = new MyClass();
                Type type = myClass.GetType();
                FieldInfo[] fieldInfos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
                foreach (var fieldInfo in fieldInfos)
                {
                    Item item = new Item();
                    item.Property = fieldInfo.Name;
    
                    String fullComment = fieldInfo.CustomAttributes.ToList()[0].ToString();
                    string[] strs = fullComment.Split(new char[] { '"' });
                    item.Comment = strs[1] ;
                    item.Type = fieldInfo.FieldType.Name;
                    items.Add(item);
                }
    
                foreach (var item in items)
                {
                    Console.WriteLine(item);
                }
                Console.WriteLine("Press any key to continue...");
                Console.ReadKey();
            }
        }
    
        class MyClass
        {
            [Comment("年龄")]
            private int? age;
    
            [Comment("姓名")]
            private String name;
    
        }
    
        class Item
        {
            public String Property { get; set; }
            public String Comment { get; set; }
            public String Type { get; set; }
            public override string ToString()
            {
                return Property + " " + Type + " " + Comment;
            }
    
        }
        // 自定义一个Attribute
        public class CommentAttribute : Attribute
        {
            private String comment;
            public CommentAttribute() {
                Console.WriteLine(comment);
            }
            public CommentAttribute(string str)
            {
                this.comment = str;
            }
            public String Comment
            {
                get { return this.comment; }
            }
        }

    结果:

    希望能帮到你。

    生活愉快。

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    理解有误,因为被提取的对象就是一个字符串,不是一个类文件,只是这个字符串里面有类似c#的类文件里面的属性的代码。类似如下

    String str="//名字\n private String name;  //名字 \n private int? age;";

    而我就是得提取这里面的代码,所以无法使用反射,希望用正则完成,是因为正则可以被用户输入字符串,并识别为正则。



    • 已编辑 Trian555 2020年1月4日 6:18
    2020年1月4日 6:16
  • 至于注释的选择,你可以再按照你的意图重新编写。

    正则表达式不太会用,我这个效果一般,你多测试测试。健壮性也不够好,你自己多测试测试,仅提供思路以供选择。

    如果其中有其他的修饰符,例如public,static等,你可以改成(private 替换成\S*\s*)

    //?.*|\s*\S*\s*\S*\s*\S*;\s*
    这样的形式,\S*\s*代表一个修饰符,每多一个就加一组

     class Data
        {
            public string Property { get; set; }
            public List<string> Comment { get; set; }
            public string Type { get; set; }
        }
        class Program
        {
            static void Main(string[] args)
            {
                var v = "//名字 \n private int? age;//名字\n private String name;  ";
                v= v.Replace("//", "\n//").Replace(";",";");
                Console.WriteLine(v);
                Regex regex =new Regex(@"//?.*|\s*private\s*\S*\s*\S*;\s*");
                var m= regex.Matches(v);
                List<string> LS = new List<string>();
                List<Data> LD = new List<Data>();
               foreach(Match item in m)
               {
                    var i= item.Value;
                    LS.Add(i);
                    if (!i.Contains("/"))
                    {
                        Data  d= new Data();
                        d.Comment = LS.ToList();
                        d.Comment.RemoveAt(LS.Count - 1);
                        var p = LS.Last();
                        var dp = p.Replace("\n", string.Empty).Replace("\r", string.Empty).Trim().Split(' ');
                        d.Property = dp[0];
                        d.Type = dp[1];
                        LD.Add(d);
                        LS.Clear();
                    }
                    
               }
                Console.WriteLine();
               foreach (var item in LD)
                {
                    string c = string.Empty;
                    foreach (var i in item.Comment)
                        c += $"{i}   ";
                    Console.WriteLine($"type: {item.Type} property : {item.Property} comment :{ c}");
                }
                Console.ReadKey();
            }
        }



    • 已标记为答案 Trian555 2020年5月9日 5:37
    2020年1月5日 8:13