JaveScript Regex начало уточнения строки + str.replace()
Получил глупый вопрос о начале тега привязки регулярного выражения ^
, Я пытался санировать строку, чтобы проверить, является ли это палиндромом, и нашел решение использовать регулярное выражение, но не смог обернуть голову вокруг объяснений, которые я нашел для начала тега привязки строки:
Насколько я понимаю:
^
обозначает, что любое последующее выражение должно совпадать, начиная с начала строки.
Вопрос:
Почему тогда есть разница между двумя выводами ниже:
1)
let x = 'A man, a plan, a canal: Panama';
const re = new RegExp(/[^a-z]/, 'gi');
console.log(x.replace(re, '*'));
Выход: A*man**a*plan**a*canal**Panama
VS.
2)
let x = 'A man, a plan, a canal: Panama';
const re = new RegExp(/[a-z]/, 'gi');
console.log(x.replace(re, '*'));
Выход: * ***, * ****, * *****: ******
VS.
3)
let x = 'A man, a plan, a canal: Panama';
const re = new RegExp(/^[a-z]/, 'gi');
console.log(x.replace(re, '*'));
Выход: * man, a plan, a canal: Panama
Пожалуйста, дайте мне знать, если мое объяснение для каждого из приведенных выше случаев не работает:
1) Запутался об этом. Если он соответствует классу символов [a-z]
регистронезависимый + глобальный поиск, с началом привязки строки ^
означает, что он должен совпадать в начале каждой строки, не должен ли он вернуть все слова в предложении? Так как каждое слово соответствует [a-z]
нечувствительные символы, которые встречаются в начале каждой строки за глобальную итерацию поиска?
(т.е.
- находит "А" в начале
- затем на следующей итерации следует начать поиск по оставшейся строке " man"
- находит место... и переходит к поиску "человека"?
- и так далее и тому подобное...
Q: Почему тогда, когда я звоню replace
это предназначается только для не альфа-материала? Должен ли я в этом случае лечить ^
как инвертирующий [a-z]
?
2) Это кажется довольно простым, находит все случаи [a-z]
и заменяет их с началом. Обратный случай 1)
3) Также запутался в этом. Я не уверен, как это отличается от 1).
/^[a-z]/gi
для меня означает: "начиная с начала просматриваемой строки, соответствовать всем буквенным символам, без учета регистра. Повторите для глобального поиска".
По сравнению с:
1) /[^a-z]/gi
для меня означает: "сопоставить все классы символов, которые начинают каждую строку с буквенного символа. без учета регистра, повторите поиск для поиска по всему миру".
Чтобы означать, что они означают точно то же самое @_@. Пожалуйста, дайте мне знать, как у меня складывается понимание вышеупомянутых случаев.
Заранее спасибо!! -Y
2 ответа
Ваше первое выражение
[^a-z]
соответствует чему-либо, кроме букв алфавита в нижнем регистре, поэтому при замене на*
все специальные символы, такие как пробелы, запятые и двоеточия, заменяются.Ваше второе выражение
[a-z]
соответствует любой буквенной, строчной букве, поэтому упомянутые специальные символы не заменяются*
,Ваше третье выражение
^[a-z]
соответствует буквенной, строчной букве в начале строки, поэтому только первая буква заменяется*
,
Для первых двух выражений глобальный флаг g
обеспечивает замену всех символов, соответствующих указанному шаблону, независимо от их положения в строке. Для третьего шаблона, однако, так как ^
закрепляет шаблон в начале строки, заменяется только первая буква.
Как вы упомянули, i
flag обеспечивает регистронезависимость, поэтому все три шаблона работают как с прописными, так и с прописными буквами, начиная с a
в z
а также A
в Z
,
Характер ^
поэтому имеет два значения:
- Он отменяет символы в наборе символов.
- Он утверждает позицию в начале строки.
^ обозначает, что любое последующее выражение должно совпадать, начиная с начала строки.
Это только когда это первое, что есть в регулярном выражении; у него есть другие цели при использовании в другом месте:
/[^a-z]/gi
В приведенном выше регулярном выражении ^
не указывает на привязку совпадения к началу строки; он инвертирует остальное содержимое []
- поэтому приведенное выше регулярное выражение будет соответствовать любому отдельному символу, кроме az. Поскольку вы используете g
флаг будет повторять это совпадение для всех символов в строке.
/[a-z]/gi
Вышеупомянутое не инвертировано, поэтому будет соответствовать один экземпляр любого символа из az (и снова из-за g
Флаг будет повторяться, чтобы соответствовать всем этим экземплярам.)
/^[a-z]/gi
В этом последнем примере каретка привязывает совпадение к началу строки; часть в скобках будет соответствовать любому отдельному символу az. g
флаг все еще используется, поэтому регулярное выражение будет пытаться продолжить сопоставление большего количества символов позже в строке, но ни один из них, кроме первого, не будет соответствовать требованию привязки к началу, так что это в конечном итоге будет соответствовать только первому символ (если он находится в пределах az), точно так же, как если бы g
Флаг не использовался.
(Когда используется где-либо в регулярном выражении, кроме начала регулярного выражения или начала []
группа, ^
будет рассматриваться как буквальный ^
.)
Если вы пытаетесь обнаружить палиндромы, вы захотите удалить все, кроме буквенных символов (и, вероятно, захотите преобразовать все в один и тот же буквенный регистр, вместо того, чтобы обнаруживать это "P" == "p":)
const isPalindrome = function(input) {
let str = input.toLowerCase().replace(/[^a-z]/g,'');
return str === str.split('').reverse().join('')
}
console.log(isPalindrome("Able was I, ere I saw Elba!"))
console.log(isPalindrome("No, it never propagates if I set a ”gap“ or prevention."))
console.log(isPalindrome("Are we not pure? “No, sir!” Panama’s moody Noriega brags. “It is garbage!” Irony dooms a man –– a prisoner up to new era."))
console.log(isPalindrome("Taco dog is not a palindrome."))