需求:string str = "Name=abc,Balance=123,GoodID=100891,OnlinePay=True,BankCardNumber=6225998999900982"字符串的规则:
1、数字都是正整数
2、如果 Balance == 0 时,没有 GoodID=100... 这一部分,而是:OT=1 这样的,即:
   string str = "Name=abc,Balance=0,OT=1,OnlinePay=True,BankCardNumber=6225998999900982"
3、如果 OnlinePay=False 时,没有 BankCardNumber=... 这一部分,而是:Memo=abcdef.. 字符串,即:
   string str = "Name=abc,Balance=0,OT=1,OnlinePay=False,Memo=abcdef"
4、以上 2 种例外可以同时存在:
   string str = "Name=abc,Balance=10,GoodID=123,OnlinePay=True,BankCardNumber=6225998999900982"
   string str = "Name=abc,Balance=10,GoodID=123,OnlinePay=False,Memo=A1VD"
   string str = "Name=abc,Balance=0,OT=3,OnlinePay=False,Memo=A2VDvb"
5、有很多这样的字符串,用回车分隔,原串示例:Name=abc,Balance=100,GoodID=123,OnlinePay=True,BankCardNumber=6225998
Name=ced,Balance=10,GoodID=124,OnlinePay=False,Memo=A1VD
Name=frg,Balance=0,OT=3,OnlinePay=False,Memo=A2VDvb
Name=frgg,Balance=0,OT=4,OnlinePay=True,BankCardNumber=955998
....
要求用正则表达式提取每行的值到数据表中:DataTable:
---------------------------------------------------------------------------------------------
Name     Balance            GoodID       OT          OnlinePay       BankCardNumber     Memo
---------------------------------------------------------------------------------------------
abc      100                123                      True            6225998
ced      10                 124                      False                              A1VD
frg      0                               3           False                              A2VDvb
frgg     0                               4           True            955998
.....
请高手指教,谢谢
   

解决方案 »

  1.   

    需要正则吗?如此规律的文本,直接逐行读取.然后Split一下,比正则快多了
      

  2.   

    由于效率原因(数据很多),要求是一个正则1次匹配出所有的结果:Regex regex = new Regex(@"求表达式", RegexOptions....);for (Match m = regex.Match(FileContent); m.Success; m = m.NextMatch())
    {
        string Name = m.Groups["Name"].Value 之类的
         string Balance = m.Groups["Balance"].Value
        string GoodID = m.Groups["GoodID"].Value;    如果 Balance = 0, GoodID = "";
        ....    增加新行到 DataTable
    }
      

  3.   

    正则适合模糊匹配,效率十分差的.
    按照楼主的需求,十分的有规律,直接Split是最快的
    等下丢代码出来
      

  4.   

    由于效率原因(数据很多),要求是一个正则1次匹配出所有的结果: <--正因为数据太大了,所以不推荐使用正则,而且不可能一次,一个正则就捞取出所有你需要的资料楼主想复杂了.. ..我这样描述一下你的需求,你看对不对呢
    我有一张Table tbA 
    栏位如下:Name,Balance,GoodID,OT,OnlinePay,BankCardNumber,Memo 
    其中Name是主键,Balance,OnlinePay两个栏位不为NULL,其他都可以为NULL
    把目前有的字串资料转换成ROW,插入到这个表中
    因此,只要把每行SPLIT出来就OK,然后用BatchUpdate 到Table中
      

  5.   

    需求正确,谢谢。
    但不想用 split,趁机会研究一下正则表达式
      

  6.   

    Regex regex = new Regex(@"Name=(?<Name>[^,]+?),Balance=(?<Balance>[^,]+?),(?<GoodID>(GoodID=([^,]+?))|(OT=(?<OT>[^,]+?))),OnlinePay=(?<OnlinePay>[^,]+?),((BankCardNumber=(?<BankCardNumber>[.]+?))|(Memo=(?<Memo>[.]+?)))", RegexOptions.IgnoreCase | RegexOptions.Compiled);
    我写的这个,可以匹配出来一部分,分析如下:
    虽然中间  GoodID, OT 二部分用的是 | 或的关系,但当适配了一条后,后面的字符串都只适配相同规则的了,即:第一行如果 Balance = 0, 则适配出了有 OT 的所有行
    郁闷中...
      

  7.   

    Regex regex = new Regex(@"Name=(?<Name>[^,]+?),Balance=(?<Balance>[^,]+?),(GoodID=(?<GoodID>[^,]+?),){0,1}(OT=(?<OT>[^,]+?),){0,1}OnlinePay=(?<OnlinePay>[^,]+?),(BankCardNumber=(?<BankCardNumber>[.]+?),){0,1}(Memo=(?<Memo>[.]+?)){0,1}", RegexOptions.IgnoreCase | RegexOptions.Compiled);这样也不行,一行也没有
      

  8.   

    Regex regex = new Regex(@"Name=(?<Name>[^,]+?),Balance=(?<Balance>[^,]+?),(GoodID=(?<GoodID>[^,]+?),){0,1}(OT=(?<OT>[^,]+?),){0,1}OnlinePay=(?<OnlinePay>[^,]+?),(BankCardNumber=(?<BankCardNumber>[^\s]+?)\s){0,1}(Memo=(?<Memo>[^\s]+?)){0,1}\s", RegexOptions.IgnoreCase | RegexOptions.Compiled);        DataTable dt = BuildEmptyDataTable();         MatchCollection mc = regex.Matches(TextBox1.Text);
            foreach (Match m in mc)
            {
                DataRow dr = dtParts.NewRow();
                dr["Name"] = m.Groups["Name"].ToString();
                dr["Balance"] = m.Groups["Balance"].ToString();
                dr["GoodID"] = m.Groups["GoodID"].ToString();
                dr["OT"] = m.Groups["OT"].ToString();
                dr["OnlinePay"] = m.Groups["OnlinePay"].ToString();
                dr["BankCardNumber"] = m.Groups["BankCardNumber"].ToString();
                dr["Memo"] = m.Groups["Memo"].ToString();
                dt.Rows.Add(dr);
            }        return dt;在源串的最后加一个回车,这样都适配出来了。我这种写法是不是很笨啊,有高手搞个漂亮简单的结果指点一下,谢谢!
      

  9.   

    try...            string test = @"Name=abc,Balance=100,GoodID=123,OnlinePay=True,BankCardNumber=6225998 
    Name=ced,Balance=10,GoodID=124,OnlinePay=False,Memo=A1VD 
    Name=frg,Balance=0,OT=3,OnlinePay=False,Memo=A2VDvb 
    Name=frgg,Balance=0,OT=4,OnlinePay=True,BankCardNumber=955998 
    ";
                DataTable dt = new DataTable();
                dt.Columns.Add("Name");
                dt.Columns.Add("Balance");
                dt.Columns.Add("GoodID");
                dt.Columns.Add("OT");
                dt.Columns.Add("OnlinePay");
                dt.Columns.Add("BankCardNumber");
                dt.Columns.Add("Memo");
                DataRow dr = dt.NewRow();            Regex reg = new Regex(@"(?im)^Name=(?<na>[a-z]+),Balance=(?<ba>\d+),(?:OT=(?<ot>\d+),)?(GoodID=(?<go>\d+),)?OnlinePay=(?<on>True|False),(BankCardNumber=(?<bc>\d+))?(?:Memo=(?<me>[a-z0-9]+))?\s*$");
                MatchCollection mc = reg.Matches(test);
                foreach (Match m in mc)
                {
                    dr = dt.NewRow();
                    dr["Name"] = m.Groups["na"].Value ;
                    dr["Balance"] = m.Groups["ba"].Value ;
                    dr["GoodID"] = m.Groups["go"].Value ;
                    dr["OT"] = m.Groups["ot"].Value;
                    dr["OnlinePay"] = m.Groups["on"].Value;
                    dr["BankCardNumber"] = m.Groups["bc"].Value;
                    dr["Memo"] = m.Groups["me"].Value;
                    dt.Rows.Add(dr);
                }
                dataGridView1.DataSource = dt;
      

  10.   

    lxcnn(过客)的正解,不过楼主提及到的"由于效率原因(数据很多),要求是一个正则1次匹配出所有的结果"这个需求是与正则违背的.正则绝对不适合匹配大文本.就过客的例子而言,他使用" string test = ...." 来放置需要匹配的文本,如果是要匹配一个150W笔资料的TXT该怎么办? file.ReadAllText 然后再reg.Matches(test); ? 绝对不现实的,我4G内存直接被吃掉光,然后报内存溢出的错误.下一楼我给对比代码,以及我测试所用的TXT,内含大概 150W行资料
      

  11.   

    WinForm程式,放置一个Button,一个Textbox,两个Datagridview
    测试文本自行去创建,150W的文本有100Mb..
    经测试
    1.Split方式:使用流一行一行的读取,然后Splite的方式,150W行耗时 14秒
    2.正则匹配的方式:直接内存溢出报错
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Text.RegularExpressions;namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }        int linecount = 0;
            private void button1_Click(object sender, EventArgs e)
            {
                DataTable dtSplit = GetDataTable();
                DataTable dtRegExp = GetDataTable();
                DateTime begintime;
                DateTime endtime ;
                double spendseconds = 0;            begintime = DateTime.Now;
                SetValueBySplit(dtSplit);
                endtime = DateTime.Now;
                spendseconds = endtime.Subtract(begintime).TotalSeconds;
                textBox1.Text += "共计" + linecount.ToString() + "行,使用Split耗费:" + spendseconds.ToString() + "秒        ";
                dataGridView1.DataSource = dtSplit;
                begintime = DateTime.Now;
                SetValueByRegExp(dtRegExp);
                endtime = DateTime.Now;
                spendseconds = endtime.Subtract(begintime).TotalSeconds;
                textBox1.Text += "使用RegExp耗费:" + spendseconds.ToString() + "秒        ";
                //dataGridView2.DataSource = dtRegExp;
            }        private  void SetValueBySplit(DataTable dt)
            {
                DataRow row = null;
                String[] strLines = null;
                String strFilePath = @"d:\test.txt";
                if (File.Exists(strFilePath))
                {
                    strLines = File.ReadAllLines(strFilePath);
                    linecount = strLines.Length;
                    foreach (string strLine in strLines)
                    {
                        row = dt.NewRow();
                        String[] strCols = strLine.Split(',');
                        foreach (String strCol in strCols)
                        {
                            int i = strCol.IndexOf('=') + 1;
                            String name = strCol.Substring(0, i - 1);
                            String value = strCol.Substring(i, strCol.Length - i);
                            row[name] = value;
                        }
                        dt.Rows.Add(row);
                    }
                }
            }        private  void SetValueByRegExp(DataTable dt)
            {
                DataRow row = null;
                Regex reg = new Regex(@"(?im)^Name=(?<na>[a-z]+),Balance=(?<ba>\d+),(?:OT=(?<ot>\d+),)?(GoodID=(?<go>\d+),)?OnlinePay=(?<on>True|False),(BankCardNumber=(?<bc>\d+))?(?:Memo=(?<me>[a-z0-9]+))?\s*$");
                MatchCollection mc = null;
                String strFilePath = @"d:\test.txt";
                String strContent = string.Empty;
                if (File.Exists(strFilePath))
                {
                    strContent = File.ReadAllText(strFilePath);
                    mc = reg.Matches(strContent);
                    foreach (Match m in mc)
                    {
                        row = dt.NewRow();
                        row["Name"] = m.Groups["na"].Value;
                        row["Balance"] = m.Groups["ba"].Value;
                        row["GoodID"] = m.Groups["go"].Value;
                        row["OT"] = m.Groups["ot"].Value;
                        row["OnlinePay"] = m.Groups["on"].Value;
                        row["BankCardNumber"] = m.Groups["bc"].Value;
                        row["Memo"] = m.Groups["me"].Value;
                        dt.Rows.Add(row);
                    }
                }
            }        private static DataTable GetDataTable()
            {
                DataTable dt = new DataTable();
                DataColumnCollection cols = dt.Columns;
                cols.Add("Name", typeof(System.String));
                cols.Add("Balance", typeof(System.String));
                cols.Add("GoodID", typeof(System.String));
                cols.Add("OT", typeof(System.String));
                cols.Add("OnlinePay", typeof(System.String));
                cols.Add("BankCardNumber", typeof(System.String));
                cols.Add("Memo", typeof(System.String));
                return dt;
            }
        }
    }
      

  12.   


    其实怎么说呢,正则有它适用的场景,在做大数据量处理,且对效率要求非常高时,大多数场合确实不适合用正则,但是在小数据量处理,或是对效率没有要求的场合,正则是一个很不错的选择,当然,只是一种选择,并不一定适用于所有人,因为每个人掌握的知识点是不一样的,这就会影响开发效率当然,我写的正则如果说会导致内存溢出,那是使用方法不当,我写的正则也可以按行来处理的,只是在处理150w数据时,效率确实不高string test = @"Name=abc,Balance=100,GoodID=123,OnlinePay=True,BankCardNumber=6225998 
    Name=ced,Balance=10,GoodID=124,OnlinePay=False,Memo=A1VD 
    Name=frg,Balance=0,OT=3,OnlinePay=False,Memo=A2VDvb 
    Name=frgg,Balance=0,OT=4,OnlinePay=True,BankCardNumber=955998";
    using (StreamWriter sw = new StreamWriter(@"g:\test.txt", true, Encoding.Default))
    {
        for (int i = 0; i <= 375000; i++)
        {
            sw.WriteLine(test);
        }
    }
    DataTable dt = new DataTable();
    dt.Columns.Add("Name");
    dt.Columns.Add("Balance");
    dt.Columns.Add("GoodID");
    dt.Columns.Add("OT");
    dt.Columns.Add("OnlinePay");
    dt.Columns.Add("BankCardNumber");
    dt.Columns.Add("Memo");
    DataRow dr = dt.NewRow();
    Stopwatch sWatch = new Stopwatch();
    sWatch.Start();
    using (StreamReader sr = new StreamReader(@"g:\test.txt", Encoding.Default))
    {
        Regex reg = new Regex(@"(?im)^Name=(?<na>[a-z]+),Balance=(?<ba>\d+),(?:OT=(?<ot>\d+),)?(GoodID=(?<go>\d+),)?OnlinePay=(?<on>True|False),(BankCardNumber=(?<bc>\d+))?(?:Memo=(?<me>[a-z0-9]+))?\s*$", RegexOptions.Compiled);
        string line = string.Empty;
        while (sr.Peek() > -1)
        {
            line = sr.ReadLine();
            Match m = reg.Match(line);
            if(m.Success)
            {
                dr = dt.NewRow();
                dr["Name"] = m.Groups["na"].Value;
                dr["Balance"] = m.Groups["ba"].Value;
                dr["GoodID"] = m.Groups["go"].Value;
                dr["OT"] = m.Groups["ot"].Value;
                dr["OnlinePay"] = m.Groups["on"].Value;
                dr["BankCardNumber"] = m.Groups["bc"].Value;
                dr["Memo"] = m.Groups["me"].Value;
                dt.Rows.Add(dr);
            }
        }
    }
    sWatch.Stop();
    textBox1.Text = "用时: " + sWatch.ElapsedMilliseconds + " ms";
    dataGridView1.DataSource = dt;
    //输出
    用时: 28607 ms
    正则并不是为某一需求而设计的,因此它要提供高度的抽象,这样就导致正则在处理某些问题时效率上有损失,当然,上面的正则还是可以优化的,但是并没有多大意义正则只用在合适的地方,而是否合适,要综合需求、开发效率、执行效率、可扩展性等等综合来考虑了