如何知道 JavaScript string.replace() 是不是做了啥?
Posted
技术标签:
【中文标题】如何知道 JavaScript string.replace() 是不是做了啥?【英文标题】:How to know if JavaScript string.replace() did anything?如何知道 JavaScript string.replace() 是否做了什么? 【发布时间】:2011-07-12 12:51:48 【问题描述】:replace
函数返回带有替换的新字符串,但如果没有要替换的单词,则返回原始字符串。除了将结果与原始字符串进行比较之外,有没有办法知道它是否真的替换了任何东西?
【问题讨论】:
为什么不想比较源字符串和修改后的字符串? 这是另一个 O(N) 操作。想象一下,我正在替换 100KB 的字符串。 好吧,如果替换发生在字符串的末尾,那么是的。但是无论如何,您的问题没有 O(1) 答案。如果需要,可以使用 match 然后替换,或者进行替换然后比较两个字符串。 @Alex - 严格来说,“另一个 O(N)”仍然是 O(N)。 在 javascript 中操作 100kb 的字符串通常是一个非常非常糟糕的主意。 【参考方案1】:一个简单的选择是在替换之前检查匹配项:
var regex = /i/g;
var newStr = str;
var replaced = str.search(regex) >= 0;
if(replaced)
newStr = newStr.replace(regex, '!');
如果您也不想这样,您可以滥用replace
回调来一次性实现:
var replaced = false;
var newStr = str.replace(/i/g, function(token)replaced = true; return '!';);
【讨论】:
请注意,String.replace 中的函数回调是 Javascript 1.3 功能 @Alnitak - 这是个问题吗?快速检查显示它于 1998 年发布,并在 IE 4 中实现! en.wikipedia.org/wiki/JavaScript#Versions 不是问题,只是谷歌(w3schools)最常返回的Javascript参考页面没有提及。 @Kobi,您的“单程”解决方案通常不起作用,我已经添加了答案。 @Kobi 第二种方法如何滥用replace
回调?【参考方案2】:
比较前后字符串是检查它是否做了任何事情的最简单方法,String.replace()
没有内在支持。
['==' 可能因错误而无法删除的人为示例]
【讨论】:
为什么要使用===
来测试两个字符串是否相等?
实际上,'0' == ''
是假的,但0 == ''
是真的——只要你在处理字符串就应该没问题。顺便说一句,===
是比较字符串中的每个字符,还是检查引用?许多语言使用字符串实习,但我不确定 JavaScript(和所有实现)。如果是这样,这绝对是最好的选择。
@Kobi,在我的人为示例中很好地抓住了 '0' 与 0,但我认为重点仍然是使用 '===' 比较字符串比使用 '== 更可靠'【参考方案3】:
Javascript replace
是设计缺陷。为什么?它与回调中的字符串替换不兼容。
例如:
"ab".replace(/(a)(b)/, "$1$2")
> "ab"
我们要验证替换是否在单次通过中完成。我想象的是这样的:
"ab".replace(/(a)(b)/, "$1$2", function replacing() console.log('ok'); )
> "ab"
真正的变种:
"ab".replace(/(a)(b)/, function replacing()
console.log('ok');
return "$1$2";
)
> ok
> "$1$2"
但函数replacing
被设计为接收$0, $1, $2, offset, string
,我们必须与替换“$1$2”作斗争。解决办法是:
"ab".replace(/(a)(b)/, function replacing()
console.log('ok');
// arguments are $0, $1, ..., offset, string
return Array.from(arguments).slice(1, -2)
.reduce(function (pattern, match, index)
// '$1' from strings like '$11 $12' shouldn't be replaced.
return pattern.replace(
new RegExp("\\$" + (index + 1) + "(?=[^\\d]|$)", "g"),
match
);
, "$1$2");
);
> ok
> "ab"
这个解决方案并不完美。字符串替换本身有自己的 WAT。例如:
"a".replace(/(a)/, "$01")
> "a"
"a".replace(/(a)/, "$001")
> "$001"
如果你想关心兼容性,你必须阅读 spec 并实现它的所有疯狂。
【讨论】:
实际上,那些“WAT”是在spec 中定义的,你不需要为此阅读nodejs源代码 @Zhegan,答案已修复。顺便说一句,这不是一个规范。这是一堆不相容的疯狂。【参考方案4】:作为一种解决方法,您可以实现自己的回调函数,该函数将设置一个标志并进行替换。 replace
的 replacement
参数可以接受函数。
【讨论】:
是的,从回调中设置一个标志是一个有趣的想法。谢谢! 据我所知,这是唯一不涉及多次搜索字符串的答案。但显然 JS 开发者并不关心性能。【参考方案5】:如果您的替换与搜索到的文本长度不同,您可以检查前后字符串的长度。我知道,这是部分响应,仅对问题的一个子集有效。
或
您可以进行搜索。如果搜索成功,则对从找到的索引开始的子字符串进行替换,然后重新组合字符串。这可能会更慢,因为您生成的是 3 个字符串而不是 2 个。
var test = "Hellllo";
var index = test.search(/ll/);
if (index >= 0)
test = test.substr(0, index - 1) + test.substr(index).replace(/ll/g, "tt");
alert(test);
【讨论】:
【参考方案6】:虽然这需要多次操作,但使用 .test()
可能就足够了:
const regex = /foo/;
const yourString = 'foo bar';
if (regex.test(yourString))
console.log('yourString contains regex');
// Go ahead and do whatever else you'd like.
The test()
method executes a search for a match between a regular expression and a specified string. Returns true or false.
【讨论】:
本题专门要求单次操作,test
表示还是需要做替换。
海事组织的最佳选择【参考方案7】:
使用indexOf
,您可以检查一个字符串是否包含另一个字符串。
看来您可能想使用它。
【讨论】:
您能详细说明一下吗?您是否建议使用indexOf
将原始结果与replace
的结果进行比较?
我建议在替换之前先做一个indexOf
。如果indexOf
返回真,那么你就会知道替换会做任何事情。
问题是indexOf不支持正则表达式
但请不要。如果效率是目标,那么在事后进行匹配后替换肯定会比'==='慢。
@AInitak,实际上search
如果正则表达式简单且足够长,则可能比比较更快。【参考方案8】:
看看 string.match() 或 string.search()
【讨论】:
你是否建议在replace
之前做一个match
以知道后者是否会做任何事情?
不,因为这意味着针对正则表达式解析字符串两次。只需在后面使用 '===' - 如果两个字符串相同,这是最快的比较。以上是关于如何知道 JavaScript string.replace() 是不是做了啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何获取 JavaScript 对象的所有属性值(不知道键)?
如何知道浏览器选项卡是不是已经使用 Javascript 打开?
如何知道何时从控制台调用 JavaScript 函数? [复制]