Patterns and modifiers

Regular expressions are a powerful way to search and replace strings.

In JavaScript, regular expressions are implemented through objects of the built-in “RegExp” class that are integrated with strings.

Note that regular expressions differ from programming language to programming language. In this tutorial, we will focus only on JavaScript. Sure, they have a lot in common, but it’s different in languages like Perl, Ruby, and PHP.

Regular expression

Regular expressions (which can be called “regexp” or “reg”) contain patterns and optional modifiers.

There are two syntax for creating a regular expression object.

Longer syntax:

regexp = new RegExp("pattern"."flags");
Copy the code

… For shorter syntax, use the slash “/” :

regexp = /pattern/; // No modifiers
regexp = /pattern/gmi; // Accompanying modifiers g, m, and I (more on that later)
Copy the code

The slash “/” tells JavaScript that we are creating a regular expression. It acts like a string quote.

usage

If you want to search within a string, you can use the search method.

Here’s an example:

let str = "I love JavaScript!"; // Will search here

let regexp = /love/;
alert( str.search(regexp) ); / / 2
Copy the code

The str.search method looks for the pattern /love/ and returns the position of the match in the string. As we can guess, /love/ is the simplest pattern. All it does is do a simple substring lookup.

The above code is equivalent to:

let str = "I love JavaScript!"; // Will search here

let substr = 'love';
alert( str.search(substr) ); / / 2
Copy the code

So searching for /love/ is equivalent to searching for “love”.

But this is only temporary. Soon we’ll be dealing with more complex regular expressions with more powerful search capabilities.

The color

The color scheme in this article is as follows:

  • The regexp –red
  • String (what we’re searching for) —blue
  • The result –green

When to usenew RegExp?

Usually we use short syntax /… /. But it doesn’t accept any variable inserts, so we have to know the exact regexp when we write the code.

New RegExp, on the other hand, allows schemas to be constructed dynamically from strings.

So we can find the fields to search and create a new RegExp based on the search fields:

let search = prompt("What you want to search?"."love");
let regexp = new RegExp(search);

// Find whatever the user wants
alert( "I love JavaScript".search(regexp));
Copy the code

The modifier

Regular expression modifiers can affect search results.

In JavaScript, there are five modifiers:

  • i

    When this modifier is used, the search is case insensitive: there is no difference between A and A (see the example below).

  • g

    When you use this modifier, the search will look for all matches, not just the first one (covered in the next chapter).

  • m

    Multiline mode (see section “Regexp-multiline” not found).

  • u

    Enable full Unicode support. This modifier modifies the treatment of proxy pairs. See the section for more details on Unicode: modifiers “u” and class \p{… }.

  • y

    Sticky mode (see the next section)

“I” modifier

The simplest modifier is I.

Example code is as follows:

let str = "I love JavaScript!";

alert( str.search(/LOVE/));// -1
alert( str.search(/LOVE/i));/ / 2
Copy the code
  1. The first search returns- 1(i.e., not found), because the search is case sensitive by default.
  2. Use modifiers/LOVE/iIn the second position of the stringlove.

The I modifier has made regular expressions more powerful than simple substring lookups. But that’s not enough. We’ll cover other modifiers and properties in the next section.

conclusion

  • A regular expression contains patterns and optional modifiers:g,i,m,u,y.
  • Without the modifiers and special flags we’ll learn about later, a regular expression search is equivalent to a substring search.
  • str.search(regexp)Method returns the index position of the found match, or if no match is found- 1.

Character classes

Consider a real task — we have a phone number, such as “+7(903)-123-45-67”, and we need to convert it to a pure number: 79035419441.

To do this, we can find and delete all non-numeric content. Character classes can help solve this problem.

A Character class is a special symbol that matches any symbol in a particular set.

First, let’s explore the “digital” class. It is written \d for “any number”.

For example, let’s find the first digit of a phone number:

let str = "+ 7 (903) - the 123-45-67";

let regexp = /\d/;

alert( str.match(regexp) ); / / 7
Copy the code

If there is no flag G, the regular expression only looks for the first match, which is the first number \d.

Let’s add the G flag to find all the numbers:

let str = "+ 7 (903) - the 123-45-67";

let regexp = /\d/g;

alert( str.match(regexp) ); // array of matches: 7,9,0,3,1,2,3,4,5,6,7

// let's make the digits-only phone number of them:
alert( str.match(regexp).join(' '));/ / 79035419441
Copy the code

This is the character class for numbers. There are other character classes.

The most commonly used are:

  • \ D (” D “from” Digit “)

    Digits: characters from 0 to 9.

  • \s (” s “from” space “)

    Space: includes space, TAB \t, newline \n and a few other rare characters, such as \v, \f and \r.

  • \w (” w “from” word “)

    Single character: Latin letters or digits or underscores _. Non-latin alphabet (such as Cyrillic or Hindi) does not belong to \ W.

For example, \d\s\w means “number” followed by “space character” followed by “single character character”, for example, 1 a.

Regular expressions may contain both regular symbol and character classes.

For example, CSS\d matches the string CSS with the following number:

let str = "Is there CSS4?";
let regexp = /CSS\d/

alert( str.match(regexp) ); // CSS4
Copy the code

We can also use a number of character classes:

alert( "I love HTML5!".match(/\s\w\w\w\w\d/));// ' HTML5'
Copy the code

Matches (each regular expression character class has a corresponding result character) :

Reverse class

For each character class, there is a “reverse class,” represented by the same letter, but written in uppercase.

“Reverse” means it matches all other characters, for example:

  • \D

    Non-numeric: Any character other than \ D, such as a letter.

  • \S

    Non – space: any character other than \s, such as a letter.

  • \W

    Non – single character: any character other than \ W, such as non – Latin letters or Spaces.

At the beginning of this chapter, we saw how to create a phone number containing only numbers from a string like +7(903)-123-45-67: Find all the numbers and concatenate them.

let str = "+ 7 (903) - the 123-45-67";

alert( str.match(/\d/g).join(' '));/ / 79031234567
Copy the code

Another quick alternative is to look for the non-numeric \D and remove it from the string:

let str = "+ 7 (903) - the 123-45-67";

alert( str.replace(/\D/g.""));/ / 79031234567
Copy the code

Dot (.) Match “any character”

Dot. Is a special character class that matches “any character except newline”.

Such as:

alert( "Z".match(/ /.));// Z
Copy the code

Or in the middle of regular expressions:

let regexp = /CS.4/;

alert( "CSS4".match(regexp) ); // CSS4
alert( "CS-4".match(regexp) ); // CS-4
alert( "CS 4".match(regexp) ); // CS 4 (space is also a character)
Copy the code

Note that the dot means “any character”, not “missing character”. There must be a matching character:

alert( "CS4".match(/CS.4/));// null, no match because there's no character for the dot
Copy the code

The dot character class with the “S” flag matches strictly any character

By default, dot and newline character \n do not match.

For example, the regular expression A.B matches A, and then matches B and any character between them, except the newline character \n:

alert( "A\nB".match(/A.B/));// null (no match)
Copy the code

In many cases, we want to use dots to represent “any character” (including newlines).

That’s what the flag S does. If there is a regular expression, then the dot. Matches virtually any character:

alert( "A\nB".match(/A.B/s) ); // A\nB (match!)
Copy the code

Firefox, IE, and Edge are not supported

Available from caniuse.com/#search=dot… Confirm to get the latest support status. As of this writing, it does not include Firefox, IE, Edge.

Fortunately, there is an alternative that can be used everywhere. We can use regular expressions such as [\s\ s] to match “any character”.

alert( "A\nB".match(/A[\s\S]B/));// A\nB (match!)
Copy the code

The pattern [\s\ s] literally: “space character or non-space character”. In other words, “anything”. We can use another pair of complementary classes, such as [\d\ d]. Or even [^] — meaning to match any character but nothing.

If we want both “points” to use the same pattern, we can also use this technique: actual points. There is a general way (” not including newlines “) and a way to match “any character” using [\s\ s] or similar forms.

Note that the blank space

Usually we pay little attention to Spaces. For us, strings 1-5 are almost the same as strings 1-5.

However, if the regular expression does not take whitespace into account, it may not work properly.

Let’s try to find numbers separated by a hyphen (-) :

alert( "1-5".match(/\d-\d/));// null, no match!
Copy the code

Let’s fix this by adding Spaces in the regular expression: \ d-\ d ‘:

alert( "1-5".match(/\d - \d/));// 1 - 5, now it works
// or we can use \s class:
alert( "1-5".match(/\d\s-\s\d/));// 1 - 5, also works
Copy the code

A space is a character. As important as any other character.

We can’t add or remove whitespace from the regular expression and expect it to work.

In other words, in regular expressions, all characters are important, and whitespace is important.

conclusion

The following character classes exist:

  • \d– number.
  • \D— Not numbers.
  • \s— Space characters, tabs, and newlines.
  • \S– in addition to\s
  • \w— Latin letters, numbers, underscores'_'.
  • \W– in addition to\w.
  • .— Anything with's'Flags a character, otherwise a division newline character\nAny character other than.

… But that’s not all!

JavaScript’s Unicode encoding for strings provides many character attributes, such as: What language does this letter belong to (if it is a letter)? Is it a punctuation mark? And so on.

We can also search by these attributes. This requires the flag U, which I’ll cover in the next article.

Anchors: The beginning of the string ^ and the end $

The caret ^ and the dollar sign $have special meaning in regular expressions. They are called anchors.

The caret ^ matches the beginning of the text, while the dollar sign $- matches the end.

For example, let’s test if the text begins with Mary:

let str1 = "Mary had a little lamb";
alert( /^Mary/.test(str1) ); // true
Copy the code

The pattern ^Mary means: string begins, followed by “Mary”.

Similarly, we can use snow$to test if the text ends with snow:

let str1 = "it's fleece was white as snow";
alert( /snow$/.test(str1) ); // true
Copy the code

In these specific cases we can actually use startsWith/endsWith instead. Regular expressions should be used for more complex tests.

Test perfect match

These two anchors ^… The $together is often used to test whether a string matches a pattern exactly. For example, testing whether the user’s input is in the correct format.

Let’s test whether a string belongs to the 12:34 time format. That is, two numbers, then a colon, then two more numbers.

In regular expression, \d\d:\d\d:

let goodInput = "O";
let badInput = "O 5";

let regexp = /^\d\d:\d\d$/;
alert( regexp.test(goodInput) ); // true
alert( regexp.test(badInput) ); // false
Copy the code

In this example, the matching text \d\d:\d\d must be immediately after the beginning of the text ^, and immediately after the end of the text $.

The entire string must conform exactly to this format. If there are any deviations or extra characters, the result will be false.

When the modifier M is present, the anchor will behave differently. We will learn later.

Anchor points have “zero width”

The anchor points ^ and $are tests. They have a width of zero.

In other words, they don’t match a specific character, but rather let the regex engine test the condition represented (beginning of text/end of text).

Flag “M” – Multi-line mode

Through the flag /… /m enables multi-line mode.

This only affects the behavior of the ^ and $anchors.

In multi-line mode, they match not only the beginning and end of text, but also the beginning and end of each line.

Line beginning ^

In this multi-line text example, the regular expression /^\d+/gm will match the beginning of each line:

let str = `1st place: Winnie
2nd place: Piglet
33rd place: Eeyore`;

alert( str.match(/^\d+/gm));/ / 1, 2, 33
Copy the code

There is no flag /… /m, only the first number is matched:

let str = `1st place: Winnie
2nd place: Piglet
33rd place: Eeyore`;

alert( str.match(/^\d+/g));/ / 1
Copy the code

This is because by default, the anchor ^ matches only the beginning of the text; in multi-line mode, it matches the beginning of the line.

The regular expression engine will look for a string in the text that begins with the anchor ^, and we will continue to match the \d+ pattern once we find it.

End of line $

The dollar sign $behaves similarly.

The regular expression ‘\w+$’ will find the last word in each line:

let str = `1st place: Winnie
2nd place: Piglet
33rd place: Eeyore`;

alert( str.match(/\w+$/gim));// Winnie,Piglet,Eeyore
Copy the code

No /… With /m flag, the dollar sign $will only match the end of the entire text, so only the last word will be found.

Anchor ^$contrast \n

To find a new line, we can use not only the anchors ^ and $, but also the newline \n.

The first difference between it and the anchors ^ and $is that, unlike anchors, it “consumes” \n and adds it (\n) to the matching result.

For example, we use it to replace $in the following code:

let str = `1st place: Winnie
2nd place: Piglet
33rd place: Eeyore`;

alert( str.match(/\w+\n/gim));// Winnie\n,Piglet\n
Copy the code

Here, we’re going to be adding a newline character every time we get a match.

There is another difference — the newline character \n does not match the end of the string. That’s why Eeyore didn’t match in the example above.

Therefore, it is often better to use anchors to match results closer to what we want.

Word boundary: \ B

The word boundary \b is a check, just like ^ and $.

When the regular expression engine (the program module that implements the search for regular expressions) encounters \ B, it checks if the position in the string is a word boundary.

There are three different positions for word boundaries:

  • At the beginning of a string, if the first character is a word character\w.
  • Between two characters in a string, one of which is a word character\wThe other one is not.
  • At the end of the string, if the last character is a word character\w.

For example, in Hello, Java! Find a word that matches \bJava\b in Hello, JavaScript! Medium is not.

alert( "Hello, Java!".match(/\bJava\b/));// Java
alert( "Hello, JavaScript!".match(/\bJava\b/));// null
Copy the code

In the string Hello, Java! In, the following positions correspond to \b:

Therefore, it matches the pattern \bHello\b because:

  1. The beginning of a string meets the first check\b.
  2. Then the words were matchedHello.
  3. And then with\bMatch again, because we’re inoAnd a space.

Pattern \bJava\b also matches. But \bHell\b (because there is no word boundary after l) and Java! \b (there is no word boundary after the exclamation mark because it is not a word \w) does not match.

alert( "Hello, Java!".match(/\bHello\b/));// Hello
alert( "Hello, Java!".match(/\bJava\b/));// Java
alert( "Hello, Java!".match(/\bHell\b/));// null (no match)
alert( "Hello, Java!".match(/\bJava! \b/));// null (no match)
Copy the code

\b can be used for both words and numbers.

For example, the pattern \b\d\d\b looks for independent two-digit numbers. In other words, it looks for two-digit numbers surrounded by characters different from \w, such as Spaces or punctuation marks (or text beginning/end).

alert( "1 23, 456, 78".match(/\b\d\d\b/g));/ / 23,78
alert( "12,34,56".match(/\b\d\d\b/g));/ / 12,34,56
Copy the code

Word boundary\bNot applicable to non-Latin letters

The word boundary test \ B checks that one side of the position matches \w, while the other side does not match “\w”.

However, \w represents the Latin letters A-Z (or numbers or underscores), so this check does not apply to other characters, such as Cyrillic letters or hieroglyphs.

Escape, special characters

As we can see, a backslash “\” is used to indicate the matching character class. So it’s a special character.

There are other special characters that have special meanings in regular expressions. They can be used to do more powerful searches.

Here is a list containing all of the special characters: [\ ^ $|? * + ().

There’s no need to try to remember them now — you’ll remember them naturally when we deal with each of them individually.

escape

To use a special character as a regular character, just precede it with a backslash.

This is also called “escaping a character”.

For example, we need to find a dot ‘.’. A dot in a regular expression means “any character except a newline”, so if we want to really represent a query for “a dot”, we can use a backslash before the dot.

alert( "Chapter 5.1".match(/\d\.\d/));/ / 5.1
Copy the code

Parentheses are also special characters, so if we want to look them up in the re, we should use \(. The following example looks for the string “g()” :

alert( "function g()".match(/g\(\)/));// "g()"
Copy the code

If we want to find backslashes \, we should use two backslashes to find:

alert( "1 \ \ 2".match(/ \ \ /));/ / '\'
Copy the code

A slash

The slash symbol ‘/’ is not a special symbol, but it is used to turn on and off regular matching in Javascript: /… pattern… /, so we should also escape it.

Here is the expression for the query slash ‘/’ :

alert( "/".match(/ / / /));/ / '/'
Copy the code

On the other hand, there is no need to escape slashes if you use a different new RegExp method:

alert( "/".match(new RegExp("/")));/ / '/'
Copy the code

Create a re instance with new RegExp

If we use new RegExp to create an instance of a regular expression, we need to do some extra escaping on it.

For example, consider the following example:

let reg = new RegExp("\d\.\d");

alert( "Chapter 5.1".match(reg) ); // null
Copy the code

It doesn’t work properly, but why?

The reason is string escape rules. Look at the following example:

alert("\d\.\d"); // d.d
Copy the code

Backslashes in strings indicate escapes or special characters such as \n that can only be used in strings. This reference “consumes” and interprets these characters, for example:

  • \n— becomes a newline character,
  • \u1234— becomes a Unicode character containing the code point,
  • . Others have no particular meaning, like\dor\zIn this case, the backslash is removed.

So calling new RegExp yields a string without a backslash.

To fix this, we need a double slash because the reference changes \\ to \ :

let regStr = "\\d\\.\\d";
alert(regStr); // \d\.\d (correct now)

let regexp = new RegExp(regStr);

alert( "Chapter 5.1".match(regexp) ); / / 5.1
Copy the code

Summary

  • Search for special characters on the literal (meaning)[\ ^ $. |? * + ()We need to put a backslash in front of them\(” Escape them “).
  • If we were in the/... /Inside (but not innew RegExpInternal), also need to escape/.
  • Pass a string (argument) tonew RegExpWhen, we need a double backslash\ \Because string quotes consume one of them.

Sets and ranges […]

In square brackets […] Several characters or character classes in the “search for any given character”.

A collection of

For example, [eao] means to find any one of the three characters ‘a’, ‘e’, or ‘O’.

This is called a set. Collections can be used in regular expressions along with other regular characters.

// find [t or m], then match "op"
alert( "Mop top".match(/[tm]op/gi));// "Mop", "top"
Copy the code

Note that although there are multiple characters in the collection, they will only correspond to one of them in the match.

So the following example will not match:

// Find "V", then match [o or I], then match "la"
alert( "Voila".match(/V[oi]la/));// null, there is no match
Copy the code

This model makes the following assumptions:

  • V.
  • And then match thoseOne character at a time [oi].
  • Then match thela.

So it could match Vola or Vila.

The scope of

Square brackets can also contain character ranges.

For example, [a-z] matches letters from a to Z, and [0-5] represents numbers from 0 to 5.

In the following example, the query matches the “X” character first, followed by two numbers or characters in the range A to F.

alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g));// xAF
Copy the code

[0-9a-f] represents two ranges: it searches for A character that meets either the numbers 0 through 9 or the letters A through F.

If we also want to find lowercase letters, we can add the range A-f: [0-9a-fa-f]. Or add the flag I.

We can also work at […] It uses character classes.

For example, if we want to find the word character \w or hyphen -, the set is [\w-].

It is also possible to combine multiple classes, for example [\s\d] for “space characters or numbers”.

A character class is a shorthand for certain character sets

Such as:

  • \d– and[0-9]The same,
  • \w– and[a-zA-Z0-9_]The same,
  • \s– and[\t\n\v\f\r ]Plus a few rare Unicode whitespace characters the same.

Out of range

In addition to normal range matching, there is something like [^… The “exclusion” range matches.

They are represented by adding the caret ^ to the beginning of the match query, which matches any character other than the given one.

Such as:

  • [^aeyo]— matches anything except'a','e','y'or'o'Characters other than.
  • [^ 0-9]— Matches any character other than a number\DTo represent.
  • [^\s]Matches any non-null character, can also be used\STo represent.

The following example queries for any character except letters, digits, and Spaces:

alert( "[email protected]".match(/[^\d\sA-Z]/gi));// @ and .
Copy the code

[in the… ] Do not escape

Usually when we do need to query for a dot character, we need to escape it as \. If we need to query a backslash, we need to use \\.

In the square bracket representation, most special characters can be used without escaping:

  • Represents a dot symbol'. '.
  • It’s a plus sign'+'.
  • It’s a parenthesis'()'.
  • ‘Pattern:’ – ‘indicates a dash at the beginning or end (where the symbol does not indicate a range).
  • Indicates a caret in a position other than the leading position (in the leading position the caret indicates exclusion)A '^'.
  • Square bracket symbol representing an opening'['.

In other words, all special characters are allowed without backslashes except those that have special meaning in square brackets.

A dot symbol “.” in square brackets represents a dot character. Query mode [.,] will look for a character that is either a dot or a comma.

In the following example, [-().^+] looks for any of the characters of -().^+ :

// There is no need to escape
let reg = /[-().^+]/g;

alert( "1 + 2-3".match(reg) ); // Match +, -
Copy the code

. But there’s no problem if you escape them “just in case” :

// Escape all characters
let reg = /[\-\(\)\.\^\+]/g;

alert( "1 + 2-3".match(reg) ); // Still works: +, -
Copy the code

quantifiers+, *,?{n}

Suppose we have a string +7(903)-123-45-67 and want to find all the numbers it contains. But unlike before, we’re not interested in individual numbers, just the whole number: 7, 903, 123, 45, 67.

A number is a sequence of one or more \d. The words used to describe the quantity we need are called quantifiers.

The number of {n}

The most obvious quantifier is the number between quotation marks: {n}. A character (or a character class, etc.) is followed by a quantifier that indicates the exact amount we need.

It has a more advanced format, as illustrated by an example:

  • Exact number of digits: {5}

    \d{5} represents a five-digit number, as \d\d\d\d\d. The next example will look for a five-digit number: alert(“I’m 12345 years old”. Match (/\d{5}/)); // “12345” we can add \b to exclude more digits: \b\d{5}\b.

  • A range of bits: {3,5}

    \d{3,5} ‘ ‘alert(“I’m not 12, but 1234 years old”. Match (/\d{3,5}/)); // “1234” we can omit upper limit. The regular expression \d{3,} looks for numbers with digits greater than or equal to 3: alert(“I’m not 12, but 345678 years old”. Match (/\d{3,}/)); / / “345678”

For the string +7(903)-123-45-67, we use \d{1,} if we need one or more consecutive digits:

let str = "+ 7 (903) - the 123-45-67";

let numbers = str.match(/\d{1,}/g);

alert(numbers); / / 7903123,45,67
Copy the code

abbreviations

Most commonly used quantifiers can have abbreviations:

  • +

    Stands for “one or more”, equivalent to {1,}. For example, \d+ is used to find all numbers: let STR = “+7(903)-123-45-67”; alert( str.match(/\d+/g) ); / / 7903123,45,67

  • ?

    Stands for “zero or one”, equivalent to {0,1}. In other words, it makes symbols optional. For example, the schema OU? R looks for o, followed by zero or a U, followed by r. So he can find or in color, as well as our in colour: let STR = “Should I write color or colour?” ; alert( str.match(/colou? r/g) ); // color, colour

  • *

    Stands for “zero or more”, equivalent to {0,}. That is, the character can appear or not appear more than once. The next example will look for a number followed by any number of zeros: alert(“100 10 1”.match(/\d0*/g)); // compare it with ‘+’ (one or more) : alert(“100 10 1”. Match (/\d0+/g)); / / 100, 10

More examples

Quantifiers are often used. They are one of the main building blocks for complex regular expressions, and we’ll look at more examples.

  • Regular expression “floating point numbers” (numbers with floating points) : \d+\.d +

    Implementation: alert (” 0, 1, 12.345 7890 “. The match (/ \ d + \ \ d + / g)); / / 12.345

  • The regular expression “Open HTML tags without attributes”, such as or

    : /<[a-z]+>/ I

    Implementation: alert(“… “.match(/<[a-z]+>/gi) ); // We look for the character ‘<‘ followed by one or more letters, and then ‘>’.

  • Regular expression “Open HTML tags without attributes” (improved version) : /<[a-z][A-z0-9]*>/ I

    Better expression: According to the standard, HTML tag names can have a number in any position except the first, such as

    . alert( “

    Hi!

    “.match(/<[a-z][a-z0-9]*>/gi) ); //

  • Regular expression “Open HTML tags without attributes” : /<\/? [a-z][a-z0-9]*>/i

    We added an optional skew bar /? . It must be escaped with a backslash, or JavaScript will assume it is the end of the pattern. alert( “

    Hi!

    “.match(/<\/? [a-z][a-z0-9]*>/gi) ); //

    ,

More precision means more complexity

We can see a common rule from these examples: The more precise the regular expression — the longer and more complex it is.

For example, HTML tags can be used with a simple regular expression: <\w+>.

Because \w represents any letter or number or ‘_’, this regular expression can also match unlabeled content, such as <_>. But it is much simpler than <[a-z][A-z0-9]*>.

Can we accept <\ W +> or do we need <[a-z][A-z0-9]*>?

In real life, both approaches are acceptable. It depends on how tolerant we are of “extra” matches and how hard it is to filter them out in other ways.

reference

Useful. Javascript. The info/regular – exp…