Тридцатиминутный пакет — регулярные выражения

внешний интерфейс JavaScript
Тридцатиминутный пакет — регулярные выражения

Введение

Регулярные выражения всем знакомы и незнакомы. Знакомство связано с тем, что в работе есть много сценариев, которые можно использовать, например, номер мобильного телефона, электронная почта, пароль и другие правила проверки.

Незнакомым является то, что регулярное выражение выглядит как набор искаженных символов, и с первого взгляда трудно понять правила сопоставления. Иногда, когда я ищу регулярное выражение для определенного правила в Интернете, результаты другие, а эффект выполнения еще менее удовлетворительный.

Сегодня я потрачу 30 минут на то, чтобы помочь вам проанализировать цель сопоставления с другой точки зрения, понять идею сопоставления и шаг за шагом научиться писать регулярные выражения (читать регулярные выражения гораздо сложнее, чем писать регулярные выражения). ).

2. Поймите, что делать с регулярностью

То, что необходимо сделать, можно резюмировать в виде следующих трех вопросов души:Q1. Что это соответствует? Q2. Что не соответствует? Q3. Сколько раз совпадать?

Q1. Что это соответствует?

Это легко понять, например, если вы хотите сопоставить символ a, напишите его прямо/a/, если позиция в строке равна a, она может быть сопоставлена:

/a/.test("javascript") //true

Чтобы сопоставить строку, начинающуюся с a, добавьте метасимволы^(идентификатор стартовой позиции),/^a/:

/^a/.test("javascript") //不是以a开头返回false
/^a/.test("abc") //是以a开头返回true

Чтобы сопоставить строки, оканчивающиеся на a, добавьте метасимволы$(идентификатор конечной позиции),/a$/:

/a$/.test("javascript") //不是以a结尾返回false
/a$/.test("cba") //是以a结尾返回true

Чтобы соответствовать символу a или b, вы можете поместить соответствующий символ в квадратные скобки/[ab]/, который соответствует до тех пор, пока строка содержит a или b:

/[ab]/.test("byte") //true

соответствует строке abc или xyz,/abc|xyz/:

/abc|xyz/.test("aabbxyz") //本字符串包含xyz,所以返回true

① Сопоставьте то, что находится перед ним (используйте просмотр вперед)

прогнозное определение(?=exp): соответствует позиции, за которой следует exp

exp1(?=exp2): соответствует exp1 перед exp2, результат сопоставления не содержит exp2

Например, чтобы сопоставить часть java перед script в строке,/java(?=script)/:

/java(?=script)/.test("javascript,javaee,typescript") //字符串中javascript符合规则 会返回ture

//1、用exec方法来验证下匹配的结果
/java(?=script)/.exec("javascript,javaee,typescript")
//2、得到匹配结果如下:
["java", index: 0, input: "javascript,javaee,typescript", groups: undefined]
//3、会发现匹配到的是java,index是0,说明找到了的是javascript中script前面的java

② Сопоставьте, что будет после (используйте после просмотра)

Обратное определение(?<=exp): соответствует позиции, которой предшествует exp

(?<=exp2)exp1: соответствует exp1 после exp2, результат сопоставления не содержит exp2

Например, чтобы соответствовать ee после java в строке,/(?<=java)ee/:

/(?<=java)ee/.test("javascript,javaee,typescript") //字符串中javaee符合规则 会返回ture

//1、用exec方法来验证下匹配的结果
/(?<=java)ee/.exec("javascript,javaee,typescript") 
//2、得到匹配结果如下:
["ee", index: 15, input: "javascript,javaee,typescript", groups: undefined]
//3、会发现匹配到的是ee,index是15,说明找到了的是javaee中java后面的ee

Q2. Что не соответствует?

Сопоставление ничто, это означает отрицание, пока это не они, оно может сопоставляться.Например, если вы не хотите сопоставлять символ а, обычное написание/[^a]/, который является метасимволом в квадратных скобках^, пока строка удовлетворяет символам, которых нет в этом наборе, она может быть сопоставлена:

/[^a]/.test("aaa") //字符串全是a,返回false
/[^a]/.test("abc") //字符串不全是a,返回true

Совпадение не начинается с a, аналогично предыдущему совпадению, плюс метасимволы^,/^[^a]/:

/^[^a]/.test("javascript") //此字符串不是以a开头,返回true
/^[^a]/.test("abc") //此字符串是以a开头,返回false

Совпадение не заканчивается на a, оно похоже на предыдущее совпадение, плюс метасимволы$,/[^a]$/:

/[^a]$/.test("javascript") //此字符串不是以a结束,返回true
/[^a]$/.test("cba") //此字符串是以a结束,返回false

Не совпадайте с символами a, b, c, вы можете поставить соответствующие символы в квадратных скобках/[^abc]/:

/[^abc]$/.test("abccba") //此字符串的字符全部都不符合,返回false

① После матча ничего нет (с использованием отрицательного прогноза)

Определение отрицательного просмотра вперед(?!exp): соответствует положению, которое не сопровождается exp

exp1(?!exp2): соответствует exp1, за которым не следует exp2, и результат сопоставления не содержит exp2

Например, чтобы сопоставить java, за которым не следует скрипт в строке,/java(?!script)/:

/java(?!script)/.test("javascript,javaee,typescript") //字符串javaee符合规则 会返回ture

//1、用exec方法来验证下匹配的结果
/java(?!script)/.exec("javascript,javaee,typescript")
//2、得到匹配结果如下:
["java", index: 11, input: "javascript,javaee,typescript", groups: undefined]
//3、会发现匹配到的是java,index是11,说明找到了的是javaee中的java,因为这个java后面是ee

② Сопоставьте то, что не впереди (используйте отрицательный просмотр назад)

отрицательное прогнозное определение(?<!exp): соответствует позиции, которой не предшествует exp

(?<!exp2)exp1: соответствует exp1, который не является exp2 впереди, и результат сопоставления не содержит exp2

Например, чтобы сопоставить скрипты, которым не предшествует java в строке,/(?<!java)script/:

/(?<!java)script/.test("javascript,javaee,typescript") //字符串中typescript符合规则 会返回ture

//1、用exec方法来验证下匹配的结果
/(?<!java)script/.exec("javascript,javaee,typescript")
//2、得到匹配结果如下:
["script", index: 22, input: "javascript,javaee,typescript", groups: undefined]
//3、会发现匹配到的是script,index是22,说明找到了的是typescript中type后面的script

③ Совпадение со строками, не содержащими последовательных букв abc.

Это довольно особое поведение при сопоставлении, если только записать его как/[^abc]/, комплект внутриОтношение. Это означает, что строка не может содержатьa,b,cЛюбой из этих трех не может определить, содержит ли строка последовательныеabc.

Затем мы должны проанализировать его под другим углом. Abc не может постоянно появляться в любой позиции строки. Мы можем использоватьнегативный взгляд впередфункции, чтобы соответствовать, а затем шаг за шагом реализовать это регулярно:

  1. За совпадающими позициями не может следовать abc, используйте отрицательный просмотр вперед для сопоставления таких позиций:/(?!abc)/
  2. За этой позицией могут следовать другие символы, используйте\wПредставлять:/(?!abc)\w/
  3. После выполнения вышеуказанных условий позицию можно использовать несколько раз подряд.+для представления количества:/((?!abc)\w)+/
  4. Чтобы покрыть каждую позицию от начала до конца, добавьте маркеры начала и конца:/^((?!abc)\w)+$/
/^((?!abc)\w)+$/.test("cbacbac") //本字符串中不包含连续的abc,结果返回true
/^((?!abc)\w)+$/.test("cbacbabc") //本字符串中包含连续的abc,结果返回false

Тут у вас еще может возникнуть вопрос: зачем использоватьнегативный взгляд вперед(Не неловко сзади), не нужнонегативный взгляд(передний не какой), просто проверить, что перед каждой позицией не стоит abc?

Ответ - нет. Поскольку регулярка проверяется с первой позиции строки, начало первой позиции любой строки пусто, поэтому первая строка не удовлетворяет условию, что начало не равно abc, поэтому она не работает.

Однако и этот случай можно использоватьпредвидениеЧтобы определить, содержит ли строка abc, достаточно ввестинегативный взгляд впередкак пользоваться.

Графический взгляд вперед и взгляд назад со значением спереди и сзади

前瞻后顾.png

Зеленые символы и позиции на рисунке были сопоставлены и обнаружены, красные в настоящее время сопоставляются и обнаруживаются, серые не сопоставляются и не обнаруживаются, а направление сопоставления — слева направо. Вперед и назад в вперед и назад см.спереди и сзади соответствующего направления, а не до или после позиции строки. Упреждающий и обратный просмотр также называются положительными утверждениями нулевой ширины и отрицательными утверждениями нулевой ширины (нулевая ширина означает только совпадающие символы, которые не соответствуют позициям), где положительные и отрицательные направления также относятся к направлению сопоставления.

Таким образом, просмотр вперед — это просмотр вперед от совпадающей позиции к началу совпадающего направления, чтобы определить, является ли символ впереди выражением; просмотр назад — это просмотр от совпадающей позиции к задней части совпадения, чтобы определить, является ли символ позади - exp; отрицательный просмотр вперед - смотреть вперед, чтобы определить, не является ли персонаж впереди exp; отрицательный просмотр назад - это смотреть назад, чтобы определить, не является ли персонаж позади exp.

Дополнительные замечания:Оглядываясь назадинегативный взглядОн не поддерживается на некоторых языках или в некоторых средах, пожалуйста, внимательно проверяйте поддержку при использовании

Чтобы лучше понять такие точки знаний, как перспективный и ретроспективный, я написал специальную аналитическую статью.Если вам интересно, вы можете прочитать "Одна картинка для просмотра вперед и назад в обычном

Q3. Сколько раз совпадать?

Соответствие один раз, вы можете сделать что-либо без определения, например соответствующий номер/\d/, если вы хотите сопоставить три последовательных числа, проще всего написать это три раза подряд:/\d\d\d/, это не проблема написать таким образом, это может соответствовать правильно.

Но если количество раз слишком много или количество раз неопределенно, это определенно не сработает, поэтому вы можете добавить правило длины:

*: совпадение любое количество раз

+: Минимум совпадение 1 раз

?: совпадение 1 или 0 раз

{m}: совпадение m раз

{m,}: минимальное совпадение m раз

{m,n}: Минимум совпадений m раз, максимум совпадений n раз, m должно быть меньше или равно n

По умолчанию используется жадное сопоставление, то есть те, которые соответствуют условиям, всегда будут совпадать.Если вы хотите предотвратить жадное сопоставление, вы можете добавить правило длины после правила.?,Например:

/\d{2,}/.exec("1234567890")
//得到匹配结果如下,会匹配到所有数字:
["1234567890", index: 0, input: "1234567890", groups: undefined]

//1、添加?,阻止非贪婪匹配后
/\d{2,}?/.exec("1234567890")
//2、得到匹配结果如下,只会匹配2个数字:
["12", index: 0, input: "1234567890", groups: undefined]

① Используйте группировку

Что если мы хотим сопоставить слово много раз, например regregregregregreg, мы видим, что reg встречается 6 раз подряд.Если мы тупо пишем 6 регов в регулярном выражении, это точно не подходит, мы можем использовать группировку для достижения , помещаем рег внутрь скобок, а затем повторяем группировку 6 раз,/(reg){6}/:

/(reg){6}/.test("regregregregregreg") //匹配成功,返回true

Однако для использования группировки таким образом необходимо предварительное условие, т. е. знание того, что совпадающая строка является reg, а затем повторение группировки. Что делать, если вы хотите сопоставить последовательные перекрывающиеся типы, такие как 8899 или 5522, но вы не уверены, что это такое? Тогда мы можем поместить перекрытие сначала в группу, а потом передать\n(n представляет количество групп) Захватите содержимое этой группы, чтобы оно соответствовало следующему:

/(\d)\1(\d)\2/.exec("2345566789")
//得到匹配结果如下,返回了5566,分组对应的5、6也被返回
["5566", "5", "6", index: 3, input: "2345566789", groups: undefined]

② Захват пакетов

Группировка по умолчанию может быть захвачена, указанная выше\1,\2это группировка, захваченная внутри регулярного выражения. Если вы хотите получить внешние данные о сопоставлении групп, вы можете использоватьRegExp.$1-$9чтобы получить. Пока регулярное выражение совпадает, оно будет. можно использоватьtest,execили ул.replaceспособ получить$1-$9.

Используйте тест:

/([a-z]{2})(\d{2})/.test("xyz123")
RegExp.$1 //返回第一个分组表达式匹配到的内容 yz
RegExp.$2 //返回第二个分组表达式匹配到的内容 12

Используйте замену:

"xyz123".replace(/([a-z]{2})(\d{2})/,'$2$1')
//会返回结果:x12yz3,就是把第一个分组匹配到的内容yz和第二个分组匹配到的内容12互换了

③ Пакет не захвачен

Если вы не хотите захватывать группу, просто добавьте ее в группу?:просто хорошо

/([a-z]{2})(?:\d{2})/.test("xyz123")
RegExp.$1 //返回第一个分组表达式匹配到的内容 yz
RegExp.$2 //分组未被捕获 返回空字符串

3. Резюме

В этой статье мы не будем вдаваться в подробности о значении метасимволов и о том, как использовать их в комбинации, это вещи, которые нужно запомнить. Вместо этого я научу вас думать о том, как разбивать регулярные выражения, как шаг за шагом анализировать требования, которые должны быть сопоставлены, и разбивать длинные и сложные требования на короткие и простые. на три вопроса души:соответствовать чему? Матч не какой? Сколько раз совпадает?для завершения регулярного выражения, которое соответствует требованиям.

Наконец, я рекомендую вам веб-сайт, который иллюстрирует регулярные шаблоны:regexper.com