【问题标题】:Split a huge text using regex delimiters使用正则表达式分隔符拆分大文本
【发布时间】:2016-06-08 14:54:45
【问题描述】:

我正在处理包含多个文件的巨型文本文件 里面的文件。这些文档具有非常相似的界面,具有固定的字段 和动态值。我需要将这些文档分隔成数组。

例子:

[
   [] <- Doc1
   [] <- Doc2
   [] <- Doc3
   [] <- Doc4
   ...
   ...
   ...
]

为此,我需要创建一个正则表达式来定义分隔符、文档的开始位置和结束位置。

例子:

DOC_START
TEXT
TEXT
TEXT
TEXT
DOC_FINAL
DOC_START
TEXT
TEXT
TEXT
TEXT
DOC_FINAL

正则表达式:((?:DOC_START)(?:[\S\S]+)(?:DOC_FINAL)?)

问题是:有些文档可能有特殊性,开始或结束时有点不同,所以我需要能够传递开始和结束选项。

我的问题:我该怎么做?以及如何改进正则表达式?

为了清楚起见,有时,文档的开头或结尾可能有点不同。示例:

DOC_START
TEXT
TEXT
TEXT
TEXT
DOC_FINAL
DOC_START
TEXT
TEXT
TEXT
TEXT
DOC_FINAL
OTHER_START
TEXT
TEXT
TEXT
TEXT
DOC_FINAL
DOC_START
TEXT
TEXT
TEXT
TEXT
OTHER_FINAL
OTHER_START
TEXT
TEXT
TEXT
TEXT
OTHER_FINAL

【问题讨论】:

  • 只是备注,不是解决方案:您的表达式可能是 [\s\S]+? - 请注意小写的 \s 和惰性运算符 (+?)。

标签: javascript regex


【解决方案1】:

最好不要使用正则表达式,尤其是对于大型文档。使用 indexOf():

 var hugeDoc = 'DOC_STARTxxDOC_ENDOTHER_STARTyyOTHER_END'; 
        var result = [];
        var start =0;

        var possibleDelimiters = [ 
                {'start': 'OTHER_START', 'end':'OTHER_END'},
                {'start': 'DOC_START', 'end':'DOC_END'}
        ];

        function parseDoc(delimiter) {
                var end = hugeDoc.indexOf(delimiter.end, start);
                if(!end) return false;
                result.push(hugeDoc.slice(start+delimiter.start.length, end));
                //add +1 here, if you have a new line after DOC_END
                start = end+delimiter.end.length;
                return true;
        }

        do {
                var found = false;
                for(ix in possibleDelimiters) {
                        var delimiter = possibleDelimiters[ix];
                        if(hugeDoc.indexOf(delimiter.start, start) === start) {
                                found = parseDoc(delimiter) || found;
                        }
                }
        } while(found);

var node = document.getElementById('result');
node.innerHTML = JSON.stringify(result);
<html>
  <body>
    <div id="result"></div>
    </body>
</html>
    

【讨论】:

    【解决方案2】:

    首先,我相信您的正则表达式中有错字,应该是[\s\S] 而不是[\S\S],注意小写的s。这正确匹配跨行。

    这个正则表达式可以完成匹配此类文档所需的功能,有人可能会做出更优化的版本:

    /(?:DOC_START|OTHER_START)([\s\S]*?)(?:DOC_FINAL|OTHER_FINAL)/g
    

    另一方面,如果可能,我宁愿建议您使用不同的方法来执行此操作。例如,如果您在 NodeJS 中执行此操作,我强烈建议您每行检查 DOC_STARTDOC_END 分隔符。然后用行填充数组,直到结束分隔符。

    假设您想要每个文档中的行数组,松散的伪代码如下:

    create resulting object ({ doc1: null })
    read line
    if start delimiter
      if current object property is null
        create array (doc#: [])
    else if end delimiter
      create new doc property (doc2: null)
    else
      add line to array
    

    另一个注意事项,如果您使用 HTML 执行此操作,我强烈建议您根本不要使用正则表达式,因为 HTML 不是常规语言 :) 您会在 SO 上找到许多指向 evil 的链接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-26
      • 1970-01-01
      • 2014-05-31
      • 1970-01-01
      • 1970-01-01
      • 2012-06-29
      • 2020-10-26
      • 1970-01-01
      相关资源
      最近更新 更多