JS字符串仅替换每隔一次
JS string replace only replacing every other occurence
我有以下JS:
"a a a a".replace(/(^|'s)a('s|$)/g, '$1')
我希望结果是''
,但反而得到了'a a'
.谁能向我解释我做错了什么?
澄清:我试图做的是删除所有被空格(即整个令牌)覆盖的'a'
这是因为这个正则表达式/(^|'s)a('s|$)/g
将上一个字符和下一个字符匹配到每个
在字符串"a a a a"
中,正则表达式匹配:
- "
- a",那么要检查的字符串就变成了"a 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; // ""
第一个"a"匹配。然后它将尝试与"a a"匹配,这将首先跳过a,然后匹配"a"。然后它将尝试与不匹配的"a"匹配。
- 第一个匹配项将替换为行首。 => '"^'"
- 然后我们有不匹配的"a"=>"a"
- 第二个匹配项将替换为"=>"
- 然后我们有不匹配的"a"=>"a"
结果将是"a"。
要获得所需的结果,您可以这样做:
"a a a a".replace(/(?:'s+a(?='s))+'s+|^a's+(?=[^a]|$|a'S)|^a|'s*a$/g, '')
正如其他人试图指出的那样,问题是正则表达式会消耗周围的空间作为匹配的一部分。这里有一个[希望]更直接的解释,说明为什么正则表达式不能按预期工作:
首先让我们分解正则表达式,它说匹配字符串的空格或开头,后跟一个"a",后跟一个空格或字符串的结尾。
现在让我们将其应用于字符串。我在字符串下面添加了字符索引,以便于谈论:
a a a a
0123456
正则表达式查看 0 索引字符,并在该位置找到一个"a",然后在索引 2 处找到一个空格。这是一个匹配项,因为它是字符串的开头,后跟一个 a 后跟一个空格。匹配的长度是 2('a' 和空格),所以我们使用两个字符并在索引 2 处开始下一次搜索。
字符 2 ('a') 既不是空格也不是字符串的开头,因此它与我们的正则表达式的开头不匹配,因此我们使用该字符(不替换它)并继续下一个字符。
字符 3 是一个空格,后跟一个"a",后跟另一个空格,与我们的正则表达式匹配。我们用一个空字符串替换它,消耗匹配的长度(3 个字符 - "a"),然后继续索引 6。
字符 6 ('a') 既不是空格也不是字符串的开头,因此它与我们的正则表达式的开头不匹配,因此我们使用该字符(不替换它)并继续下一个字符。
现在我们到了字符串的末尾,所以我们完成了。
正则表达式之所以@caeth建议(/(^|'s+)a(?='s|$)/g
)起作用是因为?=
量词。来自 MDN 正则表达式文档:
仅当 x 后跟 y 时才匹配 x。例如,
/Jack(?=Sprat)/
仅当"杰克"后跟"Sprat"时才匹配。/Jack(?=Sprat|Frost)/
仅当"Jack"后面跟着"Sprat"或"Frost"时,才会匹配它。但是,"鲱鱼"和"弗罗斯特"都不是比赛结果的一部分。
因此,在这种情况下,?=
量词会检查以下字符是否为空格,而不实际使用该字符。
(^|'s)a(?='s|$)
试试这个。替换为 $1
。请参阅演示。
https://regex101.com/r/gQ3kS4/3
请改用这个:
"a a a a".replace(/(^|'s*)a('s|$)/g, '$1')
用"*"替换所有出现的"a"
问候
或者你可以把字符串拆分开来,过滤它,然后粘回去:
"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'
。
- 我可以使用JS一次使用JSON数组中的一个字符串吗
- 一次单击一下即可在句子中显示大字符串
- 字符串拆分并获取第一次和最后一次出现
- Node.js一次替换多个字符串
- Javascript 字符串验证.如何在字符串中只写一次字符,并且只在开头写一次
- 如何使用 javascript 一次显示此数组的字符串内容
- 如何让 JavaScript 一次运行一个字符串
- 将匹配字符串中最后一次出现的点的正则表达式
- JavaScript 正则表达式,用于检查单个特殊字符是否在字符串中出现一次
- 删除/隐藏链接后最后一次出现的字符串
- JS字符串仅替换每隔一次
- 删除javascript中最后一次出现的字符串
- 如何使用String.charCodeAt();一次获取和存储字符串中每个字母的char代码值并存储它们
- Javascript Regex匹配字符串最后一次出现后的所有内容
- 在字符串中特定字符最后一次出现之前插入
- 使用javascript进行大写,每隔换行一次,并在每一新行的开头添加字符串
- regex-查找最后一次出现之前的字符串
- 一次加载两个HTML文档(从字符串加载iframe内容)
- 使用javascript replace()来匹配字符串的最后一次出现
- 缓存——一次用查询字符串更新多个js文件