【问题标题】:Why does the 'g' flag change the result of a JavaScript regular expression? [duplicate]为什么“g”标志会改变 JavaScript 正则表达式的结果? [复制]
【发布时间】:2015-09-06 08:39:17
【问题描述】:

考虑:

var reg = new RegExp("^19[-\\d]*","g");
reg.test('1973-02-01') // true
reg.test('1973-01-01') // false

为什么第三行返回false?如果我删除“g”标志,那么它会返回true

【问题讨论】:

标签: javascript regex


【解决方案1】:

在 JavaScript 中,正则表达式对象具有状态。当g 标志(“全局”)应用于它们时,这很重要,有时以奇怪的方式应用。此状态是匹配最后发生的索引,即正则表达式的.lastIndex 属性。当您再次在同一个正则表达式对象上调用 exectest 时,它会从中断处继续。

在您的示例中发生的情况是第二次调用,它从上次中断的地方开始,因此它从字符串中的第 10 个字符开始查找 - 并且在那里找不到匹配项,因为没有根本没有文本(即使有,^ 断言也不匹配)。

如果我们查看lastIndex 属性,我们可以看到发生了什么:

var reg = new RegExp("^19[-\\d]*","g");
snippet.log("Before first test: " + reg.lastIndex);
snippet.log(reg.test('1973-02-01')); //return true
snippet.log("Before second test: " + reg.lastIndex);
snippet.log(reg.test('1973-01-01')); //return false
snippet.log("After second test: " + reg.lastIndex);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

没有g标志,正则表达式对象不保持任何状态,每次都从字符串的开头开始:

var reg = new RegExp("^19[-\\d]*");
snippet.log("Before first test: " + reg.lastIndex);
snippet.log(reg.test('1973-02-01')); //return true
snippet.log("Before second test: " + reg.lastIndex);
snippet.log(reg.test('1973-01-01')); //return false
snippet.log("After second test: " + reg.lastIndex);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

旁注:一般来说,最好在 JvaScript 中使用正则表达式而不是使用 RegExp 构造函数和字符串来编写正则表达式。在你的情况下,那将是

var reg = /^19[-\d]*/g;
// or without the g flag:
var reg = /^19[-\d]*/;

旁注 2:除非您还使用 @ 987654338@(多行)标志来更改这些锚的含义。没有m,它们的意思是“输入的开始(^)或结束($)”。 使用m 标志,它们的意思是“的开始 (^) 或结束 ($)。”

【讨论】:

  • 一个好的和全面的答案(像往常一样:-)。我要添加一个注释 (3),说明如果 2 个日期字符串相同(例如,两个调用中的 '1973-02-01'),将生成完全相同的输出
  • 感谢您的解释,它有很大帮助。关于你的旁注,我认为它是`var reg = [^19[-\d]*/g;`
  • @ChopperLee:是的,我忘了删除反斜杠。 :-) 我记得当我开始 输入旁注时,但是...(现已修复)
  • 我认为您应该解释为什么使用正则表达式文字可以解决此问题。乍一看,您只是使用不同的符号来构造然后存储 RegExp 对象,并在此处重用 reg 我希望与问题中的行为相同。
  • @LightnessRacesinOrbit:使用正则表达式文字 (var reg = /^19[-\d]*/g;) 而不是 RegExp 构造函数不会解决此问题。 (jsfiddle.net/ejf08zb8) 我只是提到通常情况下,最好使用文字语法,除非您有充分的理由使用构造函数。
猜你喜欢
  • 1970-01-01
  • 2022-12-17
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 2011-05-31
  • 1970-01-01
  • 2019-01-12
  • 1970-01-01
相关资源
最近更新 更多