什么正则表达式可以沿标题分割多行(可能降价)文本?

时间:2016-12-25 20:18:24

标签: regex multiline regex-greedy

我有一个多行文字,如下所示

#####1
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

#####2
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

#####3
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

#####I
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

#####II
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

(尽管SO认为,最后还是有一个空行)。我需要沿着标题分割它,保留标题文本,并将整个事物放在字典/散列表/关联数组中/无论你使用标题文本作为键调用它们(它们都是唯一的)。

我试图迭代这些线但是我的大脑现在太过于油炸以使其正确 - 我将每个文本向前移动一个,标题1向前移动为空,并且标题II最终用标题从文本开始我

我以为我可以用正则表达式做到这一点,所以我想出了这个

#####(.+)\n([\w\W\n]+?)#

显然捕获了“下一个”#,因此它只捕获了奇怪的标题。

想法? (我与语言无关,所以请随意以你喜欢的方式回答。)

2 个答案:

答案 0 :(得分:2)

你说过任何语言,所以在VB.NET和逐行解析,这应该减少内存使用:

Option Infer On
Option Strict On

Imports System.IO
Imports System.Text

Module Module1

    Public Function GetParsedSections(s As String) As Dictionary(Of String, String)
        Dim sections As New Dictionary(Of String, String)
        ' a MemoryStream suffices here to emulate reading from a file as a stream...
        Using ms As New MemoryStream(Encoding.UTF8.GetBytes(s))
            Dim currentSectionName = ""
            Using sr As New StreamReader(ms)
                While Not sr.EndOfStream
                    Dim thisLine = sr.ReadLine()
                    If thisLine.StartsWith("#####") Then
                        ' we have a heading: update currentSectionName
                        currentSectionName = thisLine.Substring(5)
                    Else
                        ' avoid sections with no heading, i.e. preamble:
                        If currentSectionName <> "" Then
                            If sections.ContainsKey(currentSectionName) Then
                                ' note: VbCrLf represents the character sequence CRLF
                                ' add a line to the appropriate dictionary item
                                sections(currentSectionName) &= thisLine & vbCrLf
                            Else
                                ' create a new dictionary entry with the content of the current line
                                sections.Add(currentSectionName, thisLine & vbCrLf)
                            End If
                        End If
                    End If
                End While
            End Using
        End Using

        Return sections

    End Function

    Sub Main()
        Dim s = "#####1
Lo venas término que ilesa bajo abeja poniendo las tierra queman pero los los se huye entonces por muerte escaleras.

#####2

Y bajo abierta los vacía tu la me lenta talco consume quedo tierra sillas subía escaleras loca de bala mi.

Manteles y es ilesa de poniendo atrás llanura los un baja pero repartiendo los tierra venas la criaturas vacía el.

Desnudo todo quedo se los come ceniza muertos por que duro para desnuda hombrecillo aire los es los quedo bajo.

#####3
Por nino recientes arroyo quedo muelles quedo en me tu las la sillas cielo las ojos lo desnudo musgos el.

El desnudo nino los del de los luna con es vengo abrir de poniendo con fría come lentejas sillas es.

#####I
A dolor algodón buscando de de faraón apariencia cielo me los es la nino oh pasan mujer llanura de por.

Encuentro sensitivo quemadas paso los quedo musgos borrachos de recientes bajaba abierta imperturbable que al con es de y se.

#####II
Los baja comida de lenguas lenta que que y abrir quedo ballenas lo brooklyn bajaba tierra de escobazos se me.

#####1
Some more text for heading 1.

"

        Dim topics = GetParsedSections(s)

        For Each topic In topics.Keys
            Console.WriteLine("Heading: " & topic)
            Console.WriteLine(topics(topic))
        Next

        Console.ReadLine()

    End Sub

End Module

输出:

Heading: 1
Lo venas término que ilesa bajo abeja poniendo las tierra queman pero los los se huye entonces por muerte escaleras.

Some more text for heading 1.


Heading: 2

Y bajo abierta los vacía tu la me lenta talco consume quedo tierra sillas subía escaleras loca de bala mi.

Manteles y es ilesa de poniendo atrás llanura los un baja pero repartiendo los tierra venas la criaturas vacía el.

Desnudo todo quedo se los come ceniza muertos por que duro para desnuda hombrecillo aire los es los quedo bajo.


Heading: 3
Por nino recientes arroyo quedo muelles quedo en me tu las la sillas cielo las ojos lo desnudo musgos el.

El desnudo nino los del de los luna con es vengo abrir de poniendo con fría come lentejas sillas es.


Heading: I
A dolor algodón buscando de de faraón apariencia cielo me los es la nino oh pasan mujer llanura de por.

Encuentro sensitivo quemadas paso los quedo musgos borrachos de recientes bajaba abierta imperturbable que al con es de y se.


Heading: II
Los baja comida de lenguas lenta que que y abrir quedo ballenas lo brooklyn bajaba tierra de escobazos se me.

允许稍后添加部分的内容。

答案 1 :(得分:0)

好的,这很容易让人感到尴尬。事实证明,分裂#####是完全可以接受的。

articles = text.split('#####').map do |e|
  a = e.split("\n")
  [a[0], a[1..-1]]
end[1..-1].map do |e|
  ["art-#{e[0]}", e[1]]
end.to_h