Статьи

Регулярные выражения JavaScript: помимо основ

В нашем предыдущем уроке о регулярных выражениях в JavaScript вы узнали о полезности регулярных выражений и о том, как написать некоторые свои собственные для соответствия простым шаблонам.

  • Регулярные выражения
    Руководство для начинающих по регулярным выражениям в JavaScript

После прочтения предыдущего урока вы должны хорошо понимать специальные символы, такие как обратный слеш и последовательности символов, такие как \w или \W Вот очень краткое описание этих последовательностей символов:

  1. Вы можете использовать \d или \D для сопоставления цифры или нецифрового символа соответственно в любой заданной строке. Цифровые символы включают 0, 1, 2, 3, 4, 5, 6, 7, 8 и 9. Все остальные символы будут соответствовать \D
  2. Вы можете использовать \w или \W для сопоставления слова или неслова в любой заданной строке. Символы слова включают алфавиты, цифры и подчеркивание. Все остальное, например, ₹,% и т. Д., Считается не состоящим из символов.
  3. Вы можете использовать \s или \S для сопоставления пробельных или непробельных символов в строке. Пробелы включают пробел, табуляцию, перевод формы и перевод строки.

Вместо сопоставления одного символа за раз, вы можете использовать символ * чтобы соответствовать предыдущему выражению ноль или более раз. Символ + аналогично будет соответствовать предыдущему выражению 1 или более раз.

Вы можете сопоставить шаблон любое определенное количество раз, добавив к нему {n, m} . Здесь n — минимальное количество раз, которое вы хотите сопоставить, а m — максимальный предел. Если вы не укажете значение для m , предыдущее выражение будет соответствовать столько раз, сколько возможно.

Вы должны проверить мой предыдущий учебник, если что-то, что мы только что рассмотрели, не ясно. Я объяснил все более подробно там.

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

? характер означает разные вещи в разных ситуациях.

Когда используется один, этот символ соответствует выражению, которое предшествовало ему 0 или 1 раз. В этом смысле он такой же, как {0,1} .

Вы также можете использовать ? сразу после других квантификаторов, таких как * , + и {} чтобы соответствовать минимально возможному количеству символов. Другими словами, это превратит эти жадные квантификаторы в не жадных. Это может быть немного трудно понять, не смотря на живые примеры, поэтому давайте сначала рассмотрим пример.

Рассмотрим следующее предложение:

Мне был присвоен 17321HDGE в качестве идентификатора пользователя, а моему другу был назначен FHES193EK1.

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

Если мы используем выражение /\d+/g в примере, оно будет соответствовать одному или нескольким последовательным символам. Из-за глобального флага будет три матча: 17321 , 193 и 1 .

Следует отметить, что 193 и 1 считаются разными совпадениями, потому что они разделены EK .

В следующем примере показаны совпадения без использования квантификаторов.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
var re = /\d+/g;
var count = 0;
var textString = «I have been assigned 17321HDGE as user id while my friend was assigned FHES193EK1.»;
 
var match = re.exec(textString);
while(match !== null) {
  console.log(match[0]);
  match = re.exec(textString);
  count++;
}
 
console.log(«Total Matches: » + count);
 
/* Output
17321
193
1
 
Total Matches: 3
*/

Теперь, добавив ? символ после \d+ вернет девять разных совпадений. По сути, /\d+?/ Превратит каждый символ цифры в отдельное совпадение. Это почему?

Это потому, что \d+ по определению должен соответствовать одной или нескольким цифрам. С тех пор ? символ должен соответствовать минимально возможному количеству символов, он просто соответствует одной цифре за раз.

Нежадный ? на этот раз квантификатор вернет 9 меньших однозначных совпадений. Для краткости я закомментировал строку, которая записывает совпадения на консоль.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
var re = /\d+?/g;
var count = 0;
var textString = «I have been assigned 17321HDGE as user id while my friend was assigned FHES193EK1.»;
 
var match = re.exec(textString);
while(match !== null) {
  // console.log(match[0]);
  match = re.exec(textString);
  count++;
}
 
console.log(«Total Matches: » + count);
 
 
/* Output
Total Matches: 9
*/

Давайте возьмем другой пример. Регулярное выражение /\w+/ будет сохранять совпадающие символы слова до тех пор, пока они не прерываются не-словесным символом, таким как пробел. В нашем случае он будет соответствовать целым словам, разделенным пробелом, таким как назначенный и 17321HDGE один раз.

Если мы заменим наше оригинальное регулярное выражение на /\w+/ , мы получим 14 разных совпадений. По сути, каждое слово будет соответствовать своему слову. Вы можете увидеть результат самостоятельно, закомментировав строку.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
var re = /\w+/g;
var count = 0;
var textString = «I have been assigned 17321HDGE as user id while my friend was assigned FHES193EK1.»;
 
var match = re.exec(textString);
while(match !== null) {
  // console.log(match[0]);
  match = re.exec(textString);
  count++;
}
 
console.log(«Total Matches: » + count);
 
/* Output
Total Matches: 14
*/

Теперь, изменив выражение на /\w+?/ Мы вернем каждый символ слова как отдельное совпадение, и вы получите 68 совпадений.

Давайте посмотрим на последний пример, прежде чем мы продолжим. Регулярное выражение /\w{4,}/ вернет все слова в нашем предложении, которые состоят из четырех или более символов. Так что совпадения были назначены и 17321HDGE , среди прочих. Теперь переключение на /\w{4,}?/ Вернет несколько совпадений из слов с более чем четырьмя символами. В нашем примере возвращенные совпадения были бы: assi , gned , 1732 и 1HGD . Символ E в конце 17321HDGE не является частью матча потому что это не может быть в группе каких-либо четырех последовательных символов слова.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var re = /\w{4,}/g;
var count = 0;
var textString = «I have been assigned 17321HDGE as user id while my friend was assigned FHES193EK1.»;
 
var match = re.exec(textString);
while(match !== null) {
  console.log(match[0]);
  match = re.exec(textString);
  count++;
}
 
console.log(«Total Matches: » + count);
 
/* Output
have
been
assigned
17321HDGE
user
while
friend
assigned
FHES193EK1
 
Total Matches: 9
*/

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

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

на наа ннаа нана наана

Для пояснения, вы ищете жирный текст в виде совпадений: нет на нет на нет (нана) на нет . Предполагается, что часть в скобках сопоставляется как единое целое, поэтому она считается как одно совпадение.

Почти каждый, кто только начинает с регулярным выражением, будет использовать выражение /na{1,2}/ с намерением получить ожидаемый результат. По их мнению, часть {1,2} должна соответствовать одному или двум вхождениям n и a вместе. Тем не менее, он фактически соответствует одному вхождению n, за которым следуют 1 или 2 вхождения символа a .

Я пояснил совпадения, возвращенные /na{1,2}/ для пояснения: na naa n naa (na) (na) (naa) (na) . Части в скобках — это отдельные спички. Как вы можете видеть, мы не получаем желаемого результата, потому что {1,2} не рассматривает na как единое целое, которое должно быть сопоставлено.

Решение здесь состоит в том, чтобы использовать скобки, чтобы указать, что JavaScript соответствует na как единое целое. Однако, как мы видели в предыдущем уроке, JavaScript начнет запоминать совпадение из-за круглых скобок.

Если вы не хотите, чтобы JavaScript запоминал совпадение, вам придется добавить ?: Перед группой символов, которую вы пытаетесь сопоставить. В нашем случае конечным выражением станет /(?:na){1,2}/ . Группа na теперь будет сопоставлена ​​как единое целое, и она не будет запомнена. Я выделил финальные совпадения, возвращенные с этим выражением жирным шрифтом: нет на нет на нет ( нана ) на нет .

В следующем примере записываются все совпадения в консоль. Всего 6 матчей, общее количество матчей 6.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var re = /(?:na){1,2}/g;
var count = 0;
var textString = «na naa nnaa nana naana»;
 
var match = re.exec(textString);
while(match !== null) {
  console.log(match[0]);
  match = re.exec(textString);
  count++;
}
 
console.log(«Total Matches: » + count);
 
/* Output
na
na
na
nana
na
na
 
Total Matches: 6
*/

Есть много ситуаций, когда мы ищем соответствие заданному набору символов, но только если они следуют или не сопровождаются другим набором символов. Например, вы можете искать слово « яблоки» в тексте, но хотите только те совпадения, за которыми следует « . Рассмотрим следующее предложение.

яблоки вкусные. Мы ели яблоки весь день. Все, кто ел яблоки, любили их.

В приведенном выше примере мы просто хотим, чтобы первое слово соответствовало. Любое другое вхождение слова не должно быть в матчах.

Одним из способов достижения этого является использование следующего регулярного выражения a(?=b) . Слово, которое мы хотим сопоставить, — это a , а слово, которое должно идти после a, — это b . В нашем случае выражением станет /apples(?=\sare)/ . Помните, что слово не входит в этот матч.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
var re = /apples(?=\sare)/g;
var count = 0;
var textString = «apples are yummy. We ate apples all day. Everyone who ate apples liked them.»;
 
var match = re.exec(textString);
while(match !== null) {
  console.log(match[0]);
  match = re.exec(textString);
  count++;
}
 
console.log(«Total Matches: » + count);
 
/* Output
apples
 
Total Matches: 1
*/

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

Очень похожая ситуация возникнет, если вы решите подбирать яблоки только в том случае, если за ними не следует определенный набор символов. В таких случаях вам нужно заменить ?= ?! в вашем регулярном выражении. Если мы искали все вхождения яблок, за которыми не следуют, мы будем использовать /apples(?!\sare)/ качестве нашего регулярного выражения. Будет два успешных совпадения для нашего тестового предложения.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
var re = /apples(?!\sare)/g;
var count = 0;
var textString = «apples are yummy. We ate apples all day. Everyone who ate apples liked them.»;
 
var match = re.exec(textString);
while(match !== null) {
  console.log(match[0]);
  match = re.exec(textString);
  count++;
}
 
console.log(«Total Matches: » + count);
 
/* Output
apples
apples
 
Total Matches: 2
*/

Еще одна вещь — вам не нужно использовать два отдельных регулярных выражения, чтобы найти все совпадения, за которыми следует любое из двух заданных слов. Все, что вам нужно сделать, это добавить оператор канала между этими словами, и все готово. Например, если вы ищете все вхождения яблока, за которыми следуют « есть» или « были» , вы должны использовать в качестве регулярного выражения /apples(?!\sare|\swere)/ .

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

Наконец мы узнали, что ?= И ?! последовательности символов в регулярном выражении дают нам возможность возвращать определенный набор символов в качестве совпадения, только если они следуют или не сопровождаются другим данным набором символов.

Если у вас есть какие-либо вопросы, связанные с этим руководством, дайте мне знать, и я сделаю все возможное, чтобы объяснить их.