Overview of Regular Expressions

Regular expressions have wide applications in text validation, searching, and replacement. This section introduces the basic concepts of regular expressions and helps readers understand their creation and application through simple examples.

What Is a Regular Expression

Regarding text search and replacement, there are two typical applications. One is searching for files in a specified directory in Windows Explorer, usually by specifying the file name or part of the file name, and wildcard characters ? and * can be used to represent one character or any number of characters respectively — for example, *.exe represents all executable files. The other is searching and replacing in office software such as Notepad and Word. In both cases, the search text is a simple regular expression.

Often, we need to match more complex text forms, such as extracting phone numbers, mobile numbers, email addresses, etc., from a webpage’s text, or extracting substrings from a given text that start with a certain string and end with another. This requires the use of regular expressions.

A regular expression is a logical expression composed of ordinary characters and some metacharacters. Ordinary characters include digits and uppercase/lowercase letters, while metacharacters use characters or combinations of characters to express special meanings. Thus, a regular expression is essentially a combination of ordinary characters and metacharacters according to predefined rules to express the matching logic of a string. During execution, the expression is parsed to understand the intended meaning and perform matching, locating the required content.

Using Regular Expressions

Since the need for text search and replacement is common, regular expression functionality exists in various programming languages. Across different languages, the rules for writing regular expressions are almost the same; the difference lies in the syntax for compiling and processing regular expressions — that is, how they are used.

【Excel VBA】

In Excel VBA, to use regular expressions, you must first import the regex object. Enter the Excel VBA programming environment, select Tools → References, and open the References dialog box as shown in Figure 8-1. Check the Microsoft VBScript Regular Expressions 5.5 checkbox in the Available References list box, then click OK.

Document Image

Figure 8-1

Once the regex-related library is referenced, you can view it using Excel VBA’s Object Browser. Select View → Object Browser to open the Object Browser shown in Figure 8-2. In the dropdown list at the upper left, select VBScript_RegExp_55; the Classes list will display all classes in the library. Selecting a class shows all its members in the right-hand list. Selecting a member displays its description in the text box below.

In the Object Browser, the object generated by the RegExp class is the regex object. In Excel VBA, the regex object is used to implement regular expression functions, namely text search and replacement. The object generated by the MatchCollection class is a collection of matched texts after a search, the Match class represents an individual match, and the SubMatches class stores data for each group when the regular expression contains groups (for details on groups, refer to the section on capturing and non-capturing groups).

Document Image

Figure 8-2

There are two ways to create a regex object: late binding and early binding.

Late binding: Declare the variable as Object type and use CreateObject to create the regex object:

code.vba
Dim objReg As Object
Set objReg = CreateObject("VBScript.RegExp")

Early binding (two forms):

code.vba
Dim objReg As RegExp
Set objReg = New RegExp

Or

code.vba
Dim objReg As New RegExp

Both declare the variable directly as RegExp type. Compared to late binding, early binding has significantly better runtime efficiency, so it is usually preferred. Once the regex object is created, it can be combined with a regular expression to perform text search and replacement.

1. Searching

Use the RegExp object, specify the regular expression with the Pattern property, and execute the search with the Execute method. The rules for writing regular expressions will be detailed in Section 8.2; here we demonstrate with simple examples.

The results of Execute are stored in a MatchCollection collection. You can traverse each Match object (i.e., a match result) using For Each. By default, searching stops after the first match; setting the Global property of the regex object to True finds all matches; setting IgnoreCase to True makes the search case-insensitive.

The following code finds all non-digit characters in the string "A1B2C3":

code.vba
Sub Test()
    Dim objReg As New RegExp
    Dim strT As String
    Dim mcT As MatchCollection
    Dim matT As Match
    strT = "A1B2C3"
    With objReg
        .Global = True
        .Pattern = "\D"
        Set mcT = .Execute(strT)
    End With
    For Each matT In mcT
        If matT <> " " Then Debug.Print matT.Value
    Next matT
End Sub

Running this procedure outputs the matches in the Immediate Window.

2. Replacing

Use the Replace method of the regex object to replace found content with a specified string. The following code finds all non-digit characters in "A1B2C3" and replaces them with an empty string (i.e., deletes them):

code.vba
Sub Test2()
    Dim objReg As New RegExp
    Dim strT As String
    strT = "A1B2C3"
    With objReg
        .Global = True
        .Pattern = "\D"
        Debug.Print .Replace(strT, "")
    End With
End Sub

Running this procedure outputs the replaced result in the Immediate Window.

【Python】

In Python, functions provided by the re module can be used to directly search and replace strings with a given regular expression, or by creating a regex object and using its properties and methods. Search results are returned as Match objects, whose attributes and methods can be used for further display and processing.

The re module must be imported first:

code.python
>>> import re

1. Searching

The re module provides four functions for different search operations: match, search, findall, and finditer. The first two return a single match object that meets the criteria; the latter two return all matching objects.

1) re.match function

re.match starts matching from the beginning of the given text and returns None if unsuccessful. Syntax:

code.python
re.match(pattern, string, flags=0)

pattern: Regular expression for matching.

string: Text to search.

flags: Matching modifiers (see Table 8-1). Multiple flags can be combined with |, e.g., re.M | re.I.

Table 8-1 Settings of Flags

Flag Full Writing Description
re.I re.IGNORECASE Case-insensitive matching
re.M re.MULTILINE Enable multiline mode
re.S re.DOTALL Make the dot match any character, including newline characters
re.L re.LOCALE Perform locale-aware matching
re.U re.UNICODE Parse characters according to the Unicode character set
re.X re.VERBOSE Support more flexible and detailed patterns, such as multiline, ignoring whitespace, adding comments, etc.

If successful, it returns a Match object; otherwise None.

Example:

code.python
>>> import re
>>> a = 'abc123def456'
>>> m = re.match('abc', a)
>>> m
<re.Match object; span=(0, 3), match='abc'>

Case-sensitive example:

code.python
>>> b = 'aBC123dEf456'
>>> m = re.match('abc', b)
>>> m
>>> m2 = re.match('abc', b, re.I)
>>> m2
<re.Match object; span=(0, 3), match='aBC'>

2) re.search function

Unlike re.match, re.search looks through the entire string and returns the first successful match. Syntax is the same as re.match.

Example (case-insensitive search for "def"):

code.python
>>> a = 'aBC123dEf456'
>>> m = re.search('def', a, re.I)
>>> m
<re.Match object; span=(6, 9), match='dEf'>

3) re.findall function

Finds all substrings matching the regular expression and returns them as a list; returns an empty list if no match. Syntax same as re.match.

Example:

code.python
>>> a = 'aBC123dEf456abc789abC'
>>> m = re.findall('abc', a, re.I)
>>> m
['aBC', 'abc', 'abC']

4) re.finditer function

Same as re.findall but returns an iterator of match objects.

Example:

code.python
>>> a = 'aBC123dEf456abc789abC'
>>> m = re.finditer('abc', a, re.I)
>>> m
<callable_iterator object at 0x0000000005BF0F48>
>>> for i in m:
... print(i)
... 
<re.Match object; span=(0, 3), match='aBC'>
<re.Match object; span=(12, 15), match='abc'>
<re.Match object; span=(18, 21), match='abC'>

2. Replacing

Replacement means substituting matched content with a given string. Use re.sub and re.subn.

1) re.sub function

Syntax:

code.python
re.sub(pattern, repl, string, count=0, flags=0)

pattern: Regular expression.

repl: Replacement string (can be a function).

string: Original text.

count: Maximum replacements (0 = all).

flags: Matching modifiers.

Example:

code.python
>>> a = 'aBC123dEf456abc789abC'
>>> m = re.sub('abc', 'xyz', a, 0, re.I)
>>> m
'xyz123dEf456xyz789xyz'

2) re.subn function

Same as re.sub but returns a tuple: (new_string, number_of_replacements).

Example:

code.python
>>> a = 'aBC123dEf456abc789abC'
>>> m = re.subn('abc', 'xyz', a, 0, re.I)
>>> m
('xyz123dEf456xyz789xyz', 3)

You can also precompile a pattern with re.compile to create a Pattern object for repeated use.

Example:

code.python
>>> a = 'aBc123def456'
>>> p = re.compile('abc', re.I)
>>> m = p.match(a)
>>> m
<re.Match object; span=(0, 3), match='aBc'>