Javascript string regex /.*/gm не перехватывает всю строку сразу

Почему JavaScript заменяет строковую функцию?

"aaa\nbbb\nccc".replace(/.*/gm, ".")
// result = "..\n..\n.." but expected was: ".\n.\n."

"aaa\nbbb\nccc".replace(/^.*/gm, ".")
// result = ".\n.\n." -> OK!!!

"aaa\nbbb\nccc".replace(/.*$/gm, ".")
// result = "..\n..\n.." but expected was: ".\n.\n."

Что я делаю не так?

3 ответа

Решение

Позвольте мне обратиться к ним в обратном порядке:

Что я делаю не так?

Вы хотите использовать +не *, * означает ноль или более совпадений, что здесь не имеет смысла. + означает одно или несколько совпадений. Так:

"aaa\nbbb\nccc".replace(/.+/g, ".")
// ".\n.\n."

Также обратите внимание, что если вы не используете ^ или же $ (ваш первый пример), вам не нужно m модификатор (но это не было проблемой с тем, что вы делали). И тебе не нужно ^ или же $ так как . не соответствует переводу строки (что я не знал до ответа на этот вопрос).

Почему JavaScript заменяет строковую функцию?

У меня нет земных идей, и я надеюсь, что кто-то еще.

Опять же, используя * Вы говорите ноль или более совпадений. Таким образом, он соответствует всем соответствующим символам, заменяя их первой точкой; тогда это соответствует нулевым символам, заменяя их одной точкой. Результат: две точки.

Доказательство:

Живая копия | Живой источник

"aaa\nbbb\nccc".replace(/.*/g, function(m) {
    console.log("m = '" + m + "'");
});

Выходы:

m = 'ааа'
м = ''
m = 'bbb'
м = ''
m = 'ccc'
м = ''

Посмотрите на эту инструкцию:

"aaa\nbbb\nccc".replace(/(.*)/gm, ".$1.")

производит:

".aaa...
.bbb...
.ccc..."

.* Матчи aaa и заменяет его на .aaa.затем он соответствует пустой строке и заменяется на ..,

Такое же поведение при замене .* от .

Как сказал TJ Crowder, используйте вместо этого: .+

"aaa\nbbb\nccc".replace(/.+/g, ".")

Удивительно, но поведение ожидается. Пустая строка удовлетворяет регулярному выражению .*:

/.*/.test("");
// true

/.*/.exec("");
// [""]

Чтобы понять, что происходит, обратите внимание на вывод:

"aaa\nbbb\nccc".match(/.*/g);
// ["aaa", "", "bbb", "", "ccc", ""]
// m flag dropped because ^ and $ are not used

Помня, что . не совпадает \nМатч-замена производится следующим образом:

  • .* Матчи aaa
  • потому что g флаг, строка после aaa в поисках совпадения
    • .* Матчи "" - строка нулевой длины после aaa и раньше \n
    • .* не совпадает \n
    • .* Матчи bbb
    • .* Матчи "" - строка нулевой длины после bbb и раньше \n

И так далее. Просто используйте .+ чтобы избежать совпадения пустых строк.

Другие вопросы по тегам