多个正则表达式字符串模式(不同的字段)

Posted

技术标签:

【中文标题】多个正则表达式字符串模式(不同的字段)【英文标题】:Multiple Regex String Patterns (Different Fields) 【发布时间】:2015-07-08 11:17:26 【问题描述】:

我正在尝试从具有以下格式的 word 文档中提取文本并将数据插入 SQL 数据库。

Word 文档

Name of House: Aasleagh Lodge
Townland: Srahatloe
Near: Killary Harbour, Leenane
Status/Public Access: maintained, private fishing lodge
Date Built: 1838-1850, burnt 1923, rebuilt 1928

源代码

        var wordApp = new Microsoft.Office.Interop.Word.Application();
        var wordDoc = wordApp.Documents.Open(@"C:\Users\mhoban\Documents\Book.docx");
        var txt = wordDoc.Content.Text;

        var regex = new Regex(@"(Name of House\: )(.+?)[\r\n]");

        var allMatches = regex.Matches(txt);
        foreach (Match match in allMatches)
        
            var nameValue = match.Groups[2].Value;
            var townValue = match.Groups[2].Value;

            SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());
            SqlCommand com = new SqlCommand();

            com.CommandText = "INSERT INTO Houses (Name, Townland) VALUES (@name, @town)";

            com.Parameters.Add("@name", SqlDbType.NVarChar).SqlValue = nameValue;
            com.Parameters.Add("@town", SqlDbType.NVarChar).SqlValue = townValue;

            com.Connection = con;

            con.Open();

            com.ExecuteNonQuery();

            con.Close();
        

这很好用,唯一的问题是我将如何编写代码来插入其他文本字段,例如这一行

var regex = new Regex(@"(Name of House\: )(.+?)[\r\n]");

在这种情况下插入房子的名称“Aasleagh Lodge”,但我该如何写这行来插入城镇?

我尝试用我需要的字段名称替换正则表达式中的“Townland”,但我最终得到了单个记录,每个记录只包含一个不同的列值。

有没有办法我可以同时插入数据,可能是使用列表或其他东西,这样就不会发生这种情况。

新的源代码

var wordApp = new Microsoft.Office.Interop.Word.Application();
            var wordDoc = wordApp.Documents.Open(@"C:\Users\mhoban\Documents\Book.docx");
            var txt = wordDoc.Content.Text;

            using (var sr = new StringReader(txt))
            
                var s = string.Empty;
                var nameValue = new StringBuilder();
                var townValue = new StringBuilder();
                while ((s = sr.ReadLine()) != null)
                
                    if (s.StartsWith("Name of House"))
                    
                        nameValue.Append(s.Split(new[]  ':' )[1].Trim());
                    
                    else if (s.StartsWith("Townland"))
                    
                        townValue.Append(s.Split(new[]  ':' )[1].Trim());
                    

                    if (nameValue.Length > 0 && townValue.Length > 0)
                    
                        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());
                        SqlCommand com = new SqlCommand();

                        com.CommandText = "INSERT INTO Houses (Name, Townland) VALUES (@name, @town)";
                        com.CommandText = "INSERT INTO Houses (Name) VALUES (@name)";

                        com.Parameters.Add("@name", SqlDbType.NVarChar).SqlValue = nameValue;
                        com.Parameters.Add("@town", SqlDbType.NVarChar).SqlValue = townValue;

                        com.Connection = con;

                        con.Open();

                        com.ExecuteNonQuery();

                        con.Close();

                        nameValue.Clear(); townValue.Clear();
                    
                
            

数据库字段

[Id]          NCHAR (10)     NULL,
[Name]        NVARCHAR (MAX) NULL,
[Townland]    NVARCHAR (MAX) NULL,
[Near]        NVARCHAR (MAX) NULL,
[Status]      NVARCHAR (MAX) NULL,
[Built]       NVARCHAR (MAX) NULL,
[Description] NVARCHAR (MAX) NULL,
[Families]    NVARCHAR (MAX) NULL,
[Images]      IMAGE          NULL

【问题讨论】:

我不认为它可以用正则表达式来完成。您需要使用 SingleLine 选项来获取删除返回的所有行。问题是您的值在需要作为终止符返回的单词之间有空格。不用正则表达式我也能轻松做到。 @jdweng 你能给我举个例子吗? 【参考方案1】:

这是一个没有正则表达式的解决方案。这里真的不需要。

var txt = "Name of House: Aasleagh Lodge\r\nTownland: Srahatloe\r\nNear: Killary Harbour, Leenane\r\nStatus/Public Access: maintained, private fishing lodge\r\nDate Built: 1838-1850, burnt 1923, rebuilt 1928\r\nName of House: House of Lan\r\nTownland: Another town land\r\nNear: Killary Harbour, Leenane\r\nStatus/Public Access: maintained, private fishing lodge\r\nDate Built: 1838-1850, burnt 1923, rebuilt 1928\r\nName of House: New Lodge\r\nTownland: NewTownLand\r\nNear: Killary Harbour, Leenane\r\nStatus/Public Access: maintained, private fishing lodge\r\nDate Built: 1838-1850, burnt 1923, rebuilt 1928";
using (var sr = new StringReader(txt))

   var s = string.Empty;
   var nameOfHouse = new StringBuilder();
   var townland = new StringBuilder();
   while ((s = sr.ReadLine()) != null)
   
      if (s.StartsWith("Name of House"))
      
          nameOfHouse.Append(s.Split(new[] ':')[1].Trim());
      
      else if (s.StartsWith("Townland"))
      
           townland.Append(s.Split(new[]  ':' )[1].Trim());
      

      if (nameOfHouse.Length > 0 && townland.Length > 0)
       
          // INSERT THE VALUES AND RESET THEM
          nameOfHouse.Clear(); townland.Clear();
      
   

【讨论】:

我在这一行得到了一个运行时 var nameValue = splts["Name of House"];它说字典中不存在密钥 这很奇怪。您确定您发布了出现在txt 变量中的输入数据吗?我发布了我测试的数据。 请看我的屏幕。还请在您的问题中发布txt 变量的图片。 这来自一个包含 70000 多个单词的 word 文档,我发布的 word doc 示例仅适用于一所房子,只有 570 个具有相同格式的其他人...我无法将那么多文本粘贴到一个变量 好的,我已经编辑了我的答案,我假设您在每条记录中都有Name of HouseTownland。否则,我需要知道记录分隔符是什么,每条记录中的条目数是否相同,以及条目是否可能以不同的顺序出现。【参考方案2】:

您可以使用以下正则表达式:

(.*?\: )(.+?)[\r\n]

见DEMO

另外.. 您可以将正则表达式中的 [\r\n] 替换为 $ 以匹配最后一个,例如 \r or \n 是可选的。

即:

var regex = new Regex(@"^(.*?\: )(.+?)$");

【讨论】:

Regex 在这种情况下不起作用。阅读早期的 cmets。【参考方案3】:

是的,这是可能的。然而,仅仅使正则表达式通用只能解决一半的问题,因为您还必须知道每个值映射到哪个数据库列。

这是我会采取的一般方法:

    有一些东西来定义您可能在文件中遇到的每个参数名称及其在数据库中的相应列。这可能只是代码中的字典,但更成熟的设计需要将其放入某种外部配置中。

    对每一行使用基于: 的简单String.Split 将所有键/值对放入字典中(这里使用正则表达式是多余的)。

    根据上述前两步的数据构建插入语句。

【讨论】:

你能给我举个例子吗,我以前没有使用过字典或 string.split,我尝试过的所有其他方式都行不通,正则表达式是最接近的。【参考方案4】:

试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleApplication21

    class Program
    
        const string FILENAME = @"c:\temp\test.txt";
        static void Main(string[] args)
        
            StreamReader reader = new StreamReader(FILENAME);
            string inputLine = "";
            List<TakenBMI> takenBMIs = new List<TakenBMI>();
            TakenBMI newTakenBMI = null;
            while ((inputLine = reader.ReadLine()) != null)
            
                inputLine = inputLine.Trim();
                if (inputLine.Length > 0)
                
                    string[] inputArray = inputLine.Split(new char[]  ':' );
                    switch (inputArray[0].Trim())
                    
                        case "Name of House":
                            newTakenBMI = new TakenBMI();
                            takenBMIs.Add(newTakenBMI);
                            newTakenBMI.Name_of_House = inputArray[1].Trim();
                            break;
                        case "Townland":
                            newTakenBMI.Townland = inputArray[1].Trim();
                            break;
                        case "Near":
                            newTakenBMI.Near = inputArray[1].Trim();
                            break;
                        case "Status/Public Access":
                            newTakenBMI.Status_Public_Access = inputArray[1].Trim();
                            break;
                        case "Date Built":
                            newTakenBMI.Date_Built = inputArray[1].Trim();
                            break;
                    
                

            

            reader.Close();

            SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());
            con.Open();
            string SQL = "INSERT INTO Houses (Name, Townland, Near, Status, Built)" +
                "VALUES ('@name', '@town', '@near', '@status', '@built')";

            SqlCommand com = new SqlCommand(SQL,con);
           

            com.Parameters.Add("@name", SqlDbType.NVarChar);
            com.Parameters.Add("@town", SqlDbType.NVarChar);
            com.Parameters.Add("@near", SqlDbType.NVarChar);
            com.Parameters.Add("@status", SqlDbType.NVarChar);
            com.Parameters.Add("@built", SqlDbType.NVarChar);
 
            foreach (TakenBMI takenBMI in takenBMIs)
            
                com.Parameters["@name"].Value = takenBMI.Name_of_House ;
                com.Parameters["@town"].Value = takenBMI.Townland;
                com.Parameters["@near"].Value = takenBMI.Near;
                com.Parameters["@status"].Value = takenBMI.Status_Public_Access;
                com.Parameters["@built"].Value = takenBMI.Date_Built;
               
                com.ExecuteNonQuery();
            

        
    
    public class TakenBMI
    
        public string Name_of_House  get; set; 
        public string Townland  get; set; 
        public string Near  get; set; 
        public string Status_Public_Access  get; set; 
        public string Date_Built  get; set; 
    

【讨论】:

取回的数据保存在哪些变量中? List takeBMIs = new List(); 我将如何使用上述问题中所述的方式将这些数据插入数据库。 数据库中有哪些字段? 用字段更新问题

以上是关于多个正则表达式字符串模式(不同的字段)的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式验证地址字符串不包含邮政信箱模式

将字符串匹配到多个正则表达式模式并返回组号

在javascript中匹配具有多个正则表达式模式的字符串

正则表达式模式单个和多个相同字符的实例

jmeter正则表达式提取数据库查询多个字段的结果应用到下一个请求中?

在elasticsearch中搜索多个字段作为正则表达式查询