我有以下JS:
"a a a a".replace(/(^|\s)a(\s|$)/g, '$1')
我希望结果为''
,而是获得'a a'
。谁能向我解释我做错了什么?
澄清:我要做的是删除所有出现的空格({1}}被空格包围(即整个令牌)
答案 0 :(得分:2)
首先" a"火柴。 然后它将尝试匹配" a a&#34 ;,它将首先跳过a,然后匹配" a"。 然后它将尝试匹配" a",这将不匹配。
结果将是" a"。
要获得所需的结果,您可以这样做:
"a a a a".replace(/(?:\s+a(?=\s))+\s+|^a\s+(?=[^a]|$|a\S)|^a|\s*a$/g, '')
答案 1 :(得分:2)
这是因为这个正则表达式/(^|\s)a(\s|$)/g
匹配前一个字符和下一个字符到每个字符
字符串"a a a a"
中的正则表达式匹配:
修改强> 有点棘手但有效(没有正则表达式):
var a = "a a a a";
// Handle beginning case 'a '
var startI = a.indexOf("a ");
if (startI === 0){
var off = a.charAt(startI + 2) !== "a" ? 2 : 1; // test if "a" come next to keep the space before
a = a.slice(startI + off);
}
// Handle middle case ' a '
var iOf = -1;
while ((iOf = a.indexOf(" a ")) > -1){
var off = a.charAt(iOf + 3) !== "a" ? 3 : 2; // same here
a = a.slice(0, iOf) + a.slice(iOf+off, a.length);
}
// Handle end case ' a'
var endI = a.indexOf(" a");
if (endI === a.length - 2){
a = a.slice(0, endI);
}
a; // ""
答案 2 :(得分:1)
正如其他人试图指出的那样,问题是正则表达式会消耗周围的空间作为匹配的一部分。这是一个[希望]更直接的解释为什么正则表达式没有像你期望的那样工作:
首先让我们分解正则表达式,它表示匹配一个空格或字符串的开头,然后是' a'后跟一个空格或字符串的结尾。
现在让我们将它应用于字符串。我在字符串下面添加了字符索引,以便更容易讨论:
a a a a
0123456
正则表达式查看0索引字符,并找到' a'在该位置,后跟索引2处的空格。这是一个匹配,因为它是字符串的开头,后跟一个空格后跟一个空格。我们匹配的长度为2(' a'和空格),因此我们使用两个字符并在索引2处开始下一次搜索。
字符2(' a')既不是空格也不是字符串的开头,因此它与正则表达式的开头不匹配,因此我们使用该字符(不更换)它继续前进到下一个。
字符3是一个空格,后跟一个' a'然后是另一个空格,这是我们正则表达式的匹配。我们用空字符串替换它,消耗匹配的长度(3个字符 - " a")并继续索引6。
字符6(' a')既不是空格也不是字符串的开头,因此它与正则表达式的开头不匹配,因此我们使用该字符(不更换)它继续前进到下一个。
现在我们已经在字符串的末尾,所以我们已经完成了。
正则表达式@caeth建议(/(^|\s+)a(?=\s|$)/g
)之所以有效,是因为?=
量词。来自MDN Regexp Documentation:
仅当x后跟y时才匹配x。例如,
/Jack(?=Sprat)/
匹配"杰克"只有当它跟随" Sprat"。/Jack(?=Sprat|Frost)/
匹配"杰克"只有当它跟随着#34; Sprat"或者" Frost"。然而," Sprat"也不是"弗罗斯特"是比赛结果的一部分。
因此,在这种情况下,?=
量词会检查以下字符是否为空格,而不会实际消耗该字符。
答案 3 :(得分:1)
答案 4 :(得分:0)
请改用:
"a a a a".replace(/(^|\s*)a(\s|$)/g, '$1')
使用" *这将替换所有" a"出现
问候
答案 5 :(得分:0)
或者您可以将字符串拆分,过滤并将其粘合回来:
"a ba sl lf a df a a df r a".split(/\s+/).filter(function (x) { return x != "a" }).join(" ")
>>> "ba sl lf df df r"
"a a a a".split(/\s+/).filter(function (x) { return x != "a" }).join(" ")
>>> ""
或在ECMAScript 6中:
"a ba sl lf a df a a df r a".split(/\s+/).filter(x => x != "a").join(" ")
>>> "ba sl lf df df r"
"a a a a".split(/\s+/).filter(x => x != "a").join(" ")
>>> ""
我假设没有前导和尾随空格。如果要删除假设,可以将过滤器更改为x && x != 'a'
。