【问题标题】:JS regex to split by lineJS 正则表达式按行拆分
【发布时间】:2011-06-29 10:03:11
【问题描述】:

如何将一段长文本拆分成单独的行?为什么这会返回 line1 两次?

/^(.*?)$/mg.exec('line1\r\nline2\r\n');

["line1", "line1"]

我打开了多行修饰符以使^$ 匹配行的开头和结尾。我还打开了全局修饰符来捕获所有行。

我希望使用正则表达式拆分而不是 String.split,因为我将同时处理 Linux \n 和 Windows \r\n 行尾。

【问题讨论】:

    标签: javascript regex newline


    【解决方案1】:
    arrayOfLines = lineString.match(/[^\r\n]+/g);
    

    正如蒂姆所说,这既是整场比赛,也是夺冠。无论全局修饰符如何,regex.exec(string) 似乎都会返回找到第一个匹配项,而 string.match(regex) 正在尊重全局。

    【讨论】:

    • 请注意,蒂姆的会匹配空行,而我的不会。要么是可取的,要么是不可取的。
    • 旧答案,但我想说exec 在第一次匹配时返回的原因是因为它打算为全局正则表达式多次调用,直到它返回 null,并且正则表达式存储lastIndex 之类的东西,即开始下一场比赛的索引。
    • 尝试"123\n\n1234".match(/[^\r\n]+/g); 预期Array [ "123", "", "1234" ],但得到Array [ "123", "1234" ]
    【解决方案2】:

    使用

    result = subject.split(/\r?\n/);
    

    您的正则表达式返回line1 两次,因为line1 既是整个匹配项又是第一个捕获组的内容。

    【讨论】:

    • 您需要使用g 标志,而\r 在一些旧的苹果机器上是一个有效的换行符。此外,unicode 将 \u2028\u2029 和旧的 IBM 换行符 \u0085 定义为换行符。所以/[\n\u0085\u2028\u2029]|\r\n?/g 处理所有边缘情况。
    • @Mike:你确定/g 标志吗?除非明确告知,否则只有拆分一次的拆分函数没有意义。 Jojo 说他只处理 Linux 和 Windows。接下来是什么,EBCDIC?
    • @Mike:不,/g 标志不是必需的。您可以添加它,但 JavaScript 会忽略它。正如 Tim 所说,默认行为是尽可能多地拆分,但您可以使用第二个参数来施加最大值。
    • 至于什么是换行符,那就更糟了。根据Unicode Consortium,我们应该始终使用(\r\n|[\n\v\f\r\x85\u2028\u2029]),无论软件运行在什么平台上,或者数据来自哪里。
    • @Alan,非常正确。 g 标志控制是否将捕获组包含在输出中。
    【解决方案3】:

    我假设以下构成换行符

    1. \r 后跟\n
    2. \n 后跟 \r
    3. \n 单独出现
    4. \r 单独出现

    请使用

    var re=/\r\n|\n\r|\n|\r/g;
    
    arrayofLines=lineString.replace(re,"\n").split("\n");
    

    包含所有行的数组,包括空行。

    请使用

    arrayOfLines = lineString.match(/[^\r\n]+/g); 
    

    对于非空行数组

    【讨论】:

    • \n 后跟 \r 不是一个换行符
    • 在某些平台上。如果您在 C# 中检查 Environment.NewLine,您将看到 \n\r
    【解决方案4】:

    更简单的正则表达式可以处理所有行尾组合,甚至混合在同一个文件中,也可以删除空行:

    var lines = text.split(/[\r\n]+/g);

    使用空格修剪:

    var lines = text.trim().split(/\s*[\r\n]+\s*/g);

    【讨论】:

    • 第一个删除文本中间的空行,而不是开头或结尾的空行。这对我的目的来说很好,我只是为任何需要删除以保持一致的人指出这一点。
    【解决方案5】:

    首先将所有\r\n 替换为\n然后 String.split

    【讨论】:

    • 这需要两个命令。可以在一个命令中使用正则表达式完成吗?
    • @JoJo: myString.replace(/\r\n/, "\n").split("\n") (除非你是因为学术兴趣而问的:))
    • 'line1\r\nline2\r\n'.replace(/\r\n/, '\n').split('\n').without(''); 生成错误的第二个单元格:["line1", "line2\r"]
    • @JoJo:对不起,我忘记了全局的 /g 标志!应该是:myString.replace(/\r\n/g, "\n").split("\n")
    • @Jojo: 简洁地在一行中 :) 正则表达式并不是适用于所有工作的工具。它们可能非常强大,但不应该在任何地方使用。请注意,replace 一个正则表达式。
    【解决方案6】:

    Unicode 兼容的行拆分

    Unicode® 技术标准 #18 定义了 line boundaries 的构成要素。同一部分还提供了一个正则表达式来匹配所有行边界。使用该正则表达式,我们可以定义以下 JS 函数,该函数在任何行边界处拆分给定字符串(保留空行以及前导和尾随空格):

    const splitLines = s => s.split(/\r\n|(?!\r\n)[\n-\r\x85\u2028\u2029]/)
    

    我不明白为什么需要负前瞻部分 ((?!\r\n)),但这是 Unicode 文档中建议的内容?‍♂️。

    上面的文档建议定义一个正则表达式元字符来匹配所有的行结束字符和序列。 Perl has \R 为此。不幸的是,JavaScript 包含这样的元字符。唉,我什至找不到 TC39 提案。

    【讨论】:

      【解决方案7】:

      http://jsfiddle.net/uq55en5o/

      var lines = text.match(/^.*((\r\n|\n|\r)|$)/gm);

      我做过类似的事情。上面的链接是我的小提琴。

      【讨论】:

      • 这会将行分隔符留在末尾。
      猜你喜欢
      • 2012-04-20
      • 2020-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多