仅在指定字符的第一个实例上拆分字符串

时间:2011-01-05 18:26:09

标签: javascript jquery regex

在我的代码中,我根据_分割了一个字符串,然后抓住数组中的第二项。

var element = $(this).attr('class');
var field = element.split('_')[1];

接受good_luck并向我提供luck。效果很棒!

但是,现在我的课程看起来像good_luck_buddy。如何让我的javascript忽略第二个_并给我luck_buddy

我在c#stackoverflow答案中找到了这个var field = element.split(new char [] {'_'}, 2);,但它不起作用。我在jsFiddle试了一遍......

19 个答案:

答案 0 :(得分:331)

使用capturing parentheses

"good_luck_buddy".split(/_(.+)/)[1]
"luck_buddy"

它们被定义为

  

如果separator包含捕获括号,则匹配的结果为   在数组中返回。

所以在这种情况下我们想要在_.+分割(即分割分隔符是以_开头的子字符串)让结果包含我们的某些部分分隔符(即{em>一切在_之后)。

在此示例中,我们的分隔符(匹配_(.+))为_luck_buddy,捕获的组(在分隔符内)为lucky_buddy。如果没有捕获括号,luck_buddy(匹配.+)将不会包含在结果数组中,因为简单split的情况是分隔符不包含在结果中。< / p>

答案 1 :(得分:197)

你需要什么正则表达式和数组?

myString = myString.substring(myString.indexOf('_')+1)

var myString= "hello_there_how_are_you"
myString = myString.substring(myString.indexOf('_')+1)
console.log(myString)

答案 2 :(得分:27)

我不惜一切代价避免使用RegExp。这是你可以做的另一件事:

"good_luck_buddy".split('_').slice(1).join('_')

答案 3 :(得分:9)

将第一个实例替换为唯一的占位符,然后从那里拆分。

"good_luck_buddy".replace(/\_/,'&').split('&')

["good","luck_buddy"]

当需要拆分双方时,这更有用。

答案 4 :(得分:7)

借助解构分配,可以提高可读性:

let [first, ...rest] = "good_luck_buddy".split('_')
rest = rest.join('_')

答案 5 :(得分:6)

您可以使用正则表达式,如:

var arr = element.split(/_(.*)/)
<德尔> 您可以使用指定拆分限制的第二个参数。 即:     var field = element.split('_',1)[1];

答案 6 :(得分:6)

现在String.prototype.split确实允许您限制拆分次数。

str.split([separator[, limit]])

...

限制可选

一个非负整数,限制分割数。如果提供,则在每次出现指定的分隔符时拆分字符串,但是在将限制条目放置在数组中时停止。数组中根本不包含任何剩余文本。

如果在达到限制之前已到达字符串的末尾,则数组中的条目可能少于限制。 如果limit为0,则不执行拆分。

caveat

它可能无法按您期望的方式工作。我希望它会忽略其余的定界符,但是,当达到限制时,它将再次拆分剩余的字符串,并从返回结果中省略拆分后的部分。

let str = 'A_B_C_D_E'
const limit_2 = str.split('_', 2)
limit_2
(2) ["A", "B"]
const limit_3 = str.split('_', 3)
limit_3
(3) ["A", "B", "C"]

我希望得到:

let str = 'A_B_C_D_E'
const limit_2 = str.split('_', 2)
limit_2
(2) ["A", "B_C_D_E"]
const limit_3 = str.split('_', 3)
limit_3
(3) ["A", "B", "C_D_E"]

答案 7 :(得分:3)

Javascript的String.split遗憾的是无法限制实际的拆分数量。它有第二个参数,指定返回多少实际拆分项,这在您的情况下无用。解决方案是拆分字符串,关闭第一个项目,然后重新加入剩余的项目::

var element = $(this).attr('class');
var parts = element.split('_');

parts.shift(); // removes the first item from the array
var field = parts.join('_');

答案 8 :(得分:1)

获取字符串中的第一个键和其余部分的简单ES6方法是:

 const [key, ...rest] = "good_luck_buddy".split('_')
 const value = rest.join('_')
 console.log(key, value) // good, luck_buddy

答案 9 :(得分:1)

此解决方案对我有用

var str = "good_luck_buddy";
var index = str.indexOf('_');
var arr = [str.slice(0, index), str.slice(index + 1)];

//arr[0] = "good"
//arr[1] = "luck_buddy"

答案 10 :(得分:0)

如果您正在寻找一种更现代的方式来做到这一点:

let raw = "good_luck_buddy"

raw.split("_")
    .filter((part, index) => index !== 0)
    .join("_")

答案 11 :(得分:0)

这应该很快

function splitOnFirst (str, sep) {
  const index = str.indexOf(sep);
  return index < 0 ? [str] : [str.slice(0, index), str.slice(index + sep.length)];
}

答案 12 :(得分:0)

最快的解决方案?

我运行了benchmarks,该解决方案获得了巨大的成功: 1

str.slice(str.indexOf(delim) + delim.length)

// as function
function gobbleStart(str, delim) {
    return str.slice(str.indexOf(delim) + delim.length);
}

// as polyfill
String.prototype.gobbleStart = function(delim) {
    return this.slice(this.indexOf(delim) + delim.length);
};

与其他解决方案的性能比较

唯一的竞争者是同一行代码,除了使用substr而不是split

我尝试涉及splitRegExp的其他解决方案对性能造成了很大的影响,但速度却慢了两个数量级。当然,对join的结果使用split会增加性能损失。

为什么它们变慢?每当必须创建新对象或数组时,JS都必须从OS请求大块内存。这个过程很慢。

以下是一些通用准则,以防您追逐基准测试:

  • 为对象{}或数组[](如split创建的动态存储器)分配新的动态内存将花费很多性能。
  • RegExp搜索比字符串搜索更为复杂,因此速度较慢。
  • 如果您已经有一个数组,则对数组进行解构的速度与显式索引它们的速度差不多,并且看起来很棒。

移出第一个实例

这是一个解决方案,可以分割并包括第n个实例。它并没有那么快,但是在OP的问题上,gobble(element, '_', 1)仍然比RegExpsplit解决方案快2倍以上,并且可以执行更多操作:

/*
`gobble`, given a positive, non-zero `limit`, deletes
characters from the beginning of `haystack` until `needle` has
been encountered and deleted `limit` times or no more instances
of `needle` exist; then it returns what remains. If `limit` is
zero or negative, delete from the beginning only until `-(limit)`
occurrences or less of `needle` remain.
*/
function gobble(haystack, needle, limit = 0) {
  let remain = limit;
  if (limit <= 0) { // set remain to count of delim - num to leave
    let i = 0;
    while (i < haystack.length) {
      const found = haystack.indexOf(needle, i);
      if (found === -1) {
        break;
      }
      remain++;
      i = found + needle.length;
    }
  }

  let i = 0;
  while (remain > 0) {
    const found = haystack.indexOf(needle, i);
    if (found === -1) {
      break;
    }
    remain--;
    i = found + needle.length;
  }
  return haystack.slice(i);
}

根据上述定义,gobble('path/to/file.txt', '/')将提供文件名,而gobble('prefix_category_item', '_', 1)将删除前缀,就像该答案中的第一个解决方案一样。


  1. 测试是在macOSX 10.14的Chrome 70.0.3538.110中运行的。

答案 13 :(得分:0)

这是一个可以解决问题的RegExp。

'good_luck_buddy' . split(/^.*?_/)[1] 

首先,它会强制比赛从 以“ ^”开头。然后匹配任何数字 不是“ _”的字符,换句话说 第一个“ _”之前的所有字符。

“?”表示最少数量的字符 使整个模式匹配的是 与“。*?”匹配因为遵循 按“ _”,然后包含在匹配项中 作为其最后一个角色。

因此,此split()使用了这样的匹配 部分作为其“分割器”并将其从 结果。所以它删除了一切 直到并包括第一个“ _”和 给你剩下的第二个元素 结果。第一个元素是“”,代表 匹配部分之前的部分。它是 “”,因为比赛从头开始。

还有其他RegExps可以用作 很像Chandu提供的/_(.*)/ 在先前的答案中。

/^.*?_/的好处是您 可以理解它的作用 必须了解特殊角色 捕获组与replace()一起玩。

答案 14 :(得分:0)

将字符串replace()方法与regex

一起使用

var result = "good_luck_buddy".replace(/.*?_/, "");
console.log(result);

此正则表达式匹配第一个_之前的0个或多个字符以及_本身。然后用空字符串替换匹配。

答案 15 :(得分:0)

我需要字符串的两个部分,所以,regex lookbehind帮助我解决这个问题。

const full_name = 'Maria do Bairro';
const [first_name, last_name] = full_name.split(/(?<=^[^ ]+) /);
console.log(first_name);
console.log(last_name);

答案 16 :(得分:0)

这适用于Chrome + FF:

"foo=bar=beer".split(/^[^=]+=/)[1] // "bar=beer"
"foo==".split(/^[^=]+=/)[1] // "="
"foo=".split(/^[^=]+=/)[1] // ""
"foo".split(/^[^=]+=/)[1] // undefined

如果您还需要密钥,请尝试以下方法:

"foo=bar=beer".split(/^([^=]+)=/) // Array [ "", "foo", "bar=beer" ]
"foo==".split(/^([^=]+)=/) // [ "", "foo", "=" ]
"foo=".split(/^([^=]+)=/) // [ "", "foo", "" ]
"foo".split(/^([^=]+)=/) // [ "foo" ]

//[0] = ignored (holds the string when there's no =, empty otherwise)
//[1] = hold the key (if any)
//[2] = hold the value (if any)

答案 17 :(得分:0)

对于像我这样不习惯正则表达式的初学者,这种解决方案有效:

   var field = "Good_Luck_Buddy";
   var newString = field.slice( field.indexOf("_")+1 );

slice()方法提取字符串的一部分并返回一个新字符串,indexOf()方法返回字符串中第一个找到的指定值的位置。

答案 18 :(得分:0)

Mark F的解决方案非常棒,但旧浏览器不支持它。 Kennebec的解决方案非常棒,并且受到旧浏览器的支持,但不支持正则表达式。

因此,如果您正在寻找仅将字符串拆分一次的解决方案,旧浏览器支持并支持正则表达式,那么这就是我的解决方案:

&#13;
&#13;
String.prototype.splitOnce = function(regex)
{
    var match = this.match(regex);
    if(match)
    {
        var match_i = this.indexOf(match[0]);
        
        return [this.substring(0, match_i),
        this.substring(match_i + match[0].length)];
    }
    else
    { return [this, ""]; }
}

var str = "something/////another thing///again";

alert(str.splitOnce(/\/+/)[1]);
&#13;
&#13;
&#13;