正则表达式 - 应用于文本文件

时间:2011-02-21 01:10:11

标签: regex text-processing

我有一个文本文件,结构如下:

KEYWORD0 DataKey01-DataValue01 DataKey02-DataValue02 ... DataKey0N-DataValue0N

KEYWORD1 DataKey11-DataValue11 DataKey12-DataValue12 DataKey13-DataValue13 _________DataKey14-DataValue14 DataKey1N-DataValue1N (1)

// It is significant that the additional datakeys are on a new line

(1)下划线不是数据的一部分。我用它来对齐数据。

问题:如何使用正则表达式将数据转换为此格式?

<KEYWORD0>
    <DataKey00>DataValue00</DataKey00>
    <DataKey01>DataValue01</DataKey01>
    <DataKey02>DataValue02</DataKey02>
    <DataKey0N>DataValue0N</DataKey0N>
</KEYWORD0>
<KEYWORD1>
    <DataKey10>DataValue10</DataKey10>
    <DataKey11>DataValue11</DataKey11>
    <DataKey12>DataValue12</DataKey12>
    <DataKey13>DataValue12</DataKey13>
    <DataKey14>DataValue12</DataKey14>
    <DataKey1N>DataValue1N</DataKey1N>
</KEYWORD1>

4 个答案:

答案 0 :(得分:0)

^(\ w)的\ S *((\ w)的\ S *)(\ r \ n ^ \ S +(\ w)的\ S *)*

这开始进入附近但我认为这在编程语言中更容易做到...只是逐行处理文件...

答案 1 :(得分:0)

您需要在.NET中使用Regex的“组和匹配”功能,并应用以下内容:

([A-Z\d]+)(\s([A-Za-z\d]+)\-([A-Za-z\d]+))*
  1. 找到匹配并选择第一个Gruop以找到KEYWORD
  2. 遍历第3组和第4组的匹配以捕获该KEYWORD的DataKey和DataValue
  3. 转到1

答案 2 :(得分:0)

如果DataValue和DataKey项不能包含<>或' - '字符或空格,您可以执行以下操作:

使用与此类似的正则表达式以字符串形式读取文件并替换为replaceAll:([^- \t]+)-([^- \t]+)并将其用作替换(<$1>$2</$1>)。这会将这样的内容转换为DataKey01-DataValue01,如下所示:<DataKey01>DataValue01</DataKey01>

之后,您需要运行另一个全局替换,但此正则表达式^([^ \t]+)(\s+(?:<[^>]+>[^<]+</[^>]+>[\s\n]*)+)并再次替换为<$1>$2</$1>

这应该可以解决问题。

我不在VB.net中编程,所以我不知道实际语法是否正确(在某些情况下,您可能需要将\加倍或翻两倍)。您应该确保为第二次传递启用Multiline选项。

解释:

([^- \t]+)-([^- \t]+)
  • [^- \t]+)将匹配任何不包含-\t的字符串。这标记为$ 1(注意它周围的括号)
  • -将与-字符
  • 匹配
  • [^- \t]+)将再次匹配任何不包含-\t的字符串。这也标记为$ 2(注意它周围的括号)
  • 替换只会转换与ab-cd
  • 匹配的<ab>cd</ab>字符串

在此步骤之后,文件如下所示:

KEYWORD0 <DataKey00>DataValue00</DataKey00> <DataKey01>DataValue01</DataKey01>
   <DataKey02>DataValue02</DataKey02> <DataKey0N>DataValue0N</DataKey0N>

KEYWORD1 <DataKey10>DataValue10</DataKey10> <DataKey11>DataValue11</DataKey11>
   <DataKey12>DataValue12</DataKey12> <DataKey13>DataValue12</DataKey13>
   <DataKey14>DataValue12</DataKey14> <DataKey1N>DataValue1N</DataKey1N>

^([^ \t]+)(\s+(?:<[^>]+>[^<]+</[^>]+>[\s\n]*)+)

  • ^([^ \t]+)标记并匹配从该行开始的任何非\t字符串(这是$1
  • (开始标记
    • \s+空格
    • (?:非标记组从此处开始
      • <[^>]+>匹配一个开放的xml标记:<ab>
      • [^<]+匹配代码bc
      • 的内部
      • </[^>]+>匹配结束标记</ab>
      • [\s\n]*一些可选的空格或换行符
    • )+关闭未标记的组并重复至少一次
  • )关闭标记(这是$2

现在直接替换。

希望它有所帮助。

但如果这不是一次性工作,你应该尝试制作一个简单的解析器:)

答案 3 :(得分:0)

正则表达式是masochists,它是VB.NET中一个非常简单的文本解析器(从C#转换,所以检查错误):

Public Class MyFileConverter
    Public Sub Parse(inputFilename As String, outputFilename As String)
        Using reader As New StreamReader(inputFilename)
            Using writer As New StreamWriter(outputFilename)
                Parse(reader, writer)
            End Using
        End Using
    End Sub

    Public Sub Parse(reader As TextReader, writer As TextWriter)
        Dim line As String
        Dim state As Integer = 0

        Dim xmlWriter As New XmlTextWriter(writer)
        xmlWriter.WriteStartDocument()
        xmlWriter.WriteStartElement("Keywords")
        ' Root element required for conformance
        While (InlineAssignHelper(line, reader.ReadLine())) IsNot Nothing
            If line.Length = 0 Then
                If state > 0 Then
                    xmlWriter.WriteEndElement()
                End If
                state = 0
                Continue While
            End If

            Dim parts As String() = line.Split(Function(c) [Char].IsWhiteSpace(c), StringSplitOptions.RemoveEmptyEntries)
            Dim index As Integer = 0

            If state = 0 Then
                state = 1
                xmlWriter.WriteStartElement(parts(System.Math.Max(System.Threading.Interlocked.Increment(index),index - 1)))
            End If

            While index < parts.Length
                Dim keyvalue As String() = parts(index).Split("-"C)
                xmlWriter.WriteStartElement(keyvalue(0))
                xmlWriter.WriteString(keyvalue(1))
                xmlWriter.WriteEndElement()
                index += 1
            End While
        End While

        If state > 0 Then
            xmlWriter.WriteEndElement()
        End If
        xmlWriter.WriteEndElement()
        xmlWriter.WriteEndDocument()
    End Sub
    Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
        target = value
        Return value
    End Function
End Class

请注意,我在XML中添加了一个根元素,因为.Net XML对象只是像读写符合XML一样。

另请注意,该代码使用extension I wrote for String.Split