【问题标题】:Split string in javascript by lines, preserving newlines?按行拆分javascript中的字符串,保留换行符?
【发布时间】:2012-02-02 19:25:39
【问题描述】:

如何将 foo\nbar\nbaz 等 JavaScript 字符串拆分为行数组,同时保留换行符?我想得到['foo\n', 'bar\n', 'baz'] 作为输出;

我知道有很多可能的答案 - 我只是想找到一个时尚的。

对于 perl,我会使用 zero-width lookbehind assertion: split /(?<=\n)/,但它们在 javascript 正则表达式中不受支持。

PS。处理不同行尾(至少\r\n)和处理丢失的最后一个换行符(如我的示例)的额外积分。

【问题讨论】:

  • @Diodeus:有效参数。马上解决。
  • 那里。再次感谢您提醒普通用户。
  • 我在下面贴了一个正确的答案,和/(?<=\n)/一样。

标签: javascript regex newline


【解决方案1】:

您可以使用此模式执行全局匹配:/[^\n]+(?:\r?\n|$)/g

它匹配任何非换行符,然后匹配可选的\r,后跟\n,或字符串的结尾。

var input = "foo\r\n\nbar\nbaz";
var result = input.match(/[^\n]+(?:\r?\n|$)/g);

结果:["foo\r\n", "bar\n", "baz"]

【讨论】:

  • 一个缺陷:'\n'.match(/[^\n]+(?:\r?\n|$)/g) 返回null
  • 同样'\r\r\r'.match(/[^\n]+(?:\r?\n|$)/g) 返回 ['\r\r\r']
  • 我认为正则表达式应该是:/([^\r\n]*(?:\r?\n)|[^\r\n]+)/g
  • 答案不起作用,它会跳过空行。 @OlegMihailik 的正则表达式不允许 \r 在行的中间,并排除这些字符。
【解决方案2】:

这个怎么样?

"foo\nbar\nbaz".split(/^/m);

结果

["foo
", "bar
", "baz"]

【讨论】:

  • 我喜欢这种方法,但我注意到如果文本包含“\r\n”,它不会按预期工作,例如:"foo\r\n\nbar\nbaz".split(/^/m); 给出:Array(5) [ "foo\r", "\n", "\n", "bar\n", "baz" ]
【解决方案3】:

我会远离split 使用正则表达式,因为 IE 的实现失败。请改用match

"foo\nbar\nbaz".match(/^.*(\r?\n|$)/mg)

结果:["foo\n", "bar\n", "baz"]

【讨论】:

  • 如果 \r 出现在一行的中间,则排除该字符并在该点拆分。
【解决方案4】:

一种简单但粗略的方法是首先用 2 个特殊字符替换“\n”。拆分第二个,拆分后将第一个替换为“\n”。效率不高,也不优雅,但绝对有效。

【讨论】:

    【解决方案5】:

    cmets中的其他答案和答案都以不同的方式存在缺陷。我需要一个在任何字符串或文件上都能正常工作的函数。

    这是一个简单而正确的答案:

    function split_lines(s) {
        return s.match(/[^\n]*\n|[^\n]+/g);
    }
    
    input = "foo\r\n\nbar\n\r\nba\rz\r\r\r";
    
    a = split_lines(input);
    
    Array(5) [ "foo\r\n", "\n", "bar\n", "\r\n", "ba\rz\r\r\r" ]
    

    它有效地在每个换行符\n 处拆分,但包含\n,并且当且仅当它不为空时才包含不带尾随\n 的最后一行。它包括输出中的所有输入字符。我们不需要对\r 进行任何特殊处理。

    我已经在大量随机数据上对此进行了测试,它确实保留了所有输入字符,并且\n 只出现在行尾。

    这是一个测试脚本:

    function split_lines(s) {
        return s.match(/[^\n]*\n|[^\n]+/g);
    }
    
    function gen_random_string(n, ncharset=256, nlprob=0.05, crprob=0.05) {
        var s = "";
        for (let i = 0; i < n; ++i) {
            var r = Math.random();
            if (r < nlprob)
                s += "\n";
            else if (r < nlprob + crprob)
                s += "\r";
            else {
                var cc = Math.floor(r / (1 - nlprob - crprob) * ncharset);
                var c = String.fromCharCode(cc);
                s += c;
            }
        }
        return s;
    }
    
    function test(...args) {
        var s = gen_random_string(...args);
        console.log(`generated random string of length ${s.length} with args:`, ...args);
    
        var ok = true, ok1;
        var a = split_lines(s);
        console.log(`split into ${a.length} lines`);
    
        ok1 = s === a.join('');
        ok = ok && ok1;
        console.log("split lines combine to give the original string?", ok1 ? "OK" : "FAIL");
        for (var i = 0; i < a.length; ++i) {
            var s1 = a[i];
            ok1 = s1.endsWith("\n") || i == a.length-1;
            ok = ok && ok1;
            ok1 = !s1.slice(0, -1).includes("\n");
            ok = ok && ok1;
        }
        console.log("tested each line other than the last ends with \\n");
        console.log("tested each line does not contain \\n before the last character");
        console.log("Final result", ok ? "OK" : "FAIL");
    }
    
    test(10000, 256);
    test(10000, 65536);

    【讨论】:

      猜你喜欢
      • 2022-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多