## Searching with Grep

This section describes the Grep option in BBEdit's Find command, which allows you to find and change text that matches a set of conditions you specify. Combined with the multi-file search and replace features, BBEdit's grep capabilities can make many editing tasks quicker and easier, whether you are modifying Web pages, extracting data from a file, or just rearranging a phone list.

### What Is Grep Searching?

Grep searching (sometimes referred to as “pattern” or “regular expression” searching) offers a powerful way to search in and make changes to your text that "plain text" searches simply cannot. For example, suppose you have a list of people's names that you want to alphabetize. If the names appear last name first, you can easily put these names in a BBEdit window and use the Sort tool. But if the list is arranged first name first, a simple grep pattern can be used to put the names in the proper order for sorting.

A grep pattern, also known as a regular expression, describes the text that you are looking for. For instance, a pattern can describe words that begin with C and end in l. A pattern like this would match "Call", "Cornwall", and "Criminal" as well as hundreds of other words.

In fact, you have probably already used pattern searching without realizing it. The Find & Replace dialog's "Match Case" and "Entire Word" options turn on special searching patterns. Suppose that you are looking for "corn". With the "Match Case" option turned off, you are actually looking for a pattern that says: look for a C or c, O or o, R or r, and N or n. With the "Entire Word" option on, you are looking for the string "corn" only if it is surrounded by white space or punctuation characters; special search characters, called metacharacters, are added to the search string you specified to indicate this.

What makes pattern searching counterintuitive at first is how you describe the pattern. Consider the first example above, where we want to search for text that begins with the letter "C" and ends with the letter "l" with any number of letters in between. What exactly do you put between them that means "any number of letters"? That is what this chapter is all about.

###### Note

Grep is the name of a frequently used Unix command that searches using regular expressions, the same type of search pattern used by BBEdit. For this reason, you will often see regular expressions called "grep patterns," as BBEdit does. They're the same thing.

### Writing Search Patterns

This section explains how to create search patterns using BBEdit's grep syntax. For readers with prior experience, this is essentially like the syntax used for regular expressions in the Perl programming language. (However, you do not need to understand anything about Perl in order to make use of BBEdit's grep searching.)

#### Most Characters Match Themselves

Most characters that you type into the Find & Replace dialog match themselves. For instance, if you are looking for the letter "t", Grep stops and reports a match when it encounters a "t" in the text. This idea is so obvious that it seems not worth mentioning, but the important thing to remember is that these characters are search patterns. Very simple patterns, to be sure, but patterns nonetheless.

#### Escaping Special Characters

In addition to the simple character matching discussed above, there are various special characters that have different meanings when used in a grep pattern than in a normal search. (The use of these characters is covered in the following sections.)

However, sometimes you will need to include an exact, or literal, instance of these characters in your grep pattern. In this case, you must use the backslash character \ before that special character to have it be treated literally; this is known as "escaping" the special character. To search for a backslash character itself, double it \\ so that its first appearance will escape the second.

For example, perhaps the most common "special character" in grep is the dot: ".". In grep, a dot character will match any character except a return. But what if you only want to match a literal dot? If you escape the dot: "\.", it will only match another literal dot character in your text.

So, most characters match themselves, and even the special characters will match themselves if they are preceded by a backslash. BBEdit's grep syntax coloring helps make this clear.

###### Note

When passing grep patterns to BBEdit via AppleScript, be aware that both the backslash and double-quote characters have special meaning to AppleScript. In order to pass these through correctly, you must escape them in your script. Thus, to pass \r for a carriage return to BBEdit, you must write \\r in your AppleScript string.

#### Wildcards Match Types of Characters

These special characters, or metacharacters, are used to match certain types of other characters:

Wildcard | Matches...
--- | ---
. | any character except a line break (that is, a carriage return)
^ | beginning of a line (unless used in a character class)
$ | end of line (unless used in a character class)

Being able to specifically match text starting at the beginning or end of a line is an especially handy feature of grep. For example, if you wanted to find every instance of a message sent by Patrick, from a log file which contains various other information like so:

From: Rich, server: barebones.com

To: BBEdit-Talk, server: lists.barebones.com

From: Patrick, server: example.barebones.com

you could search for the pattern:

^From: Patrick

and you will find every occurrence of these lines in your file (or set of files if you do a multi-file search instead).

It is important to note that ^ and $ do not actually match return characters. They match zero-width positions after and before returns, respectively. So, if you are looking for "foo" at the end of a line, the pattern "foo$ " will match the three characters "f", "o", and "o". If you search for "foo\r ", you will match the same text, but the match will contain four characters: "f", "o", "o", and a return.

###### Note

^ and $ do not match the positions after and before soft line breaks.

You can combine ^ and $ within a pattern to force a match to constitute an entire line. For example:

^foo$

will only match "foo" on a line by itself, with no other characters. Try it against these three lines to see for yourself:

foobar
foo
fighting foo

The pattern will only match the second line.

###### Note

In versions of BBEdit prior to 6.5, the # character was a wildcard that matched any digit (0-9); however, this is no longer the case. If you have grep patterns written with an old version of BBEdit that use # for this purpose, you will need to change these patterns. The easiest way to do this is to use the \d character class, which has the exact same meaning that # used to--it matches any character from 0-9. Character classes are explained in the next section.

#### Other Positional Assertions

BBEdit's grep engine supports additional positional assertions, very similar to ^ and $.

Escape | Matches
--- | ---
\A | only at the beginning of the document (as opposed to ^, which matches at the beginning of the document and also at the beginning of each line)
\b | any word boundary, defined as any position between a \w character and a \W character, in either order
\B | any position that is not a word boundary
\z | at the end of the document (as opposed to $, which matches at the end of the document and also at the end of each line)
\Z | at the end of the document, or before a trailing return at the end of the doc, if there is one

Examples (the text matched by the pattern is underlined)

Search for: \bfoo\b

Will match: bar foo bar

Will match: foo bar

Will not match: foobar

Search for: \bJane\b

Will match: Jane's

Will match: Tell Jane about the monkey.

Search for: \Afoo

Will match: foobar

Will not match: This is good foo.

#### Character Classes Match Sets or Ranges of Characters

The character class construct lets you specify a set or a range of characters to match, or to ignore. A character class is constructed by placing a pair of square brackets [...] around the group or range of characters you wish to include. To exclude, or ignore, all characters specified by a character class, add a caret character ^ just after the opening bracket [^...]. For example:

Character Class | Matches
--- | ---
[xyz] | any one of the characters x, y, z
[^xyz] | any character except x, y, z
[a-z] | any character in the range a to z

You can use any number of characters or ranges between the brackets. Here are some examples:

Character Class | Matches
--- | ---
[aeiou] | any vowel
[^aeiou] | any character that is not a vowel
[a-zA-Z0-9] | any character from a-z, A-Z, or 0-9
[^aeiou0-9] | any character that is neither a vowel nor a digit

A character class matches when the search encounters any one of the characters in the pattern. However, the contents of a set are only treated as separate characters, not as words. For example, if your search pattern is [beans] and the text in the window is "lima beans", BBEdit will report a match at the "a" of the word "lima".

To include the character ] in a set or a range, place it immediately after the opening bracket. To use the ^ character, place it anywhere except immediately after the opening bracket. To match a dash character (hyphen) in a range, place it at the beginning of the range; to match it as part of a set, place it at the beginning or end of the set. Or, you can include any of these character at any point in the class by escaping them with a backslash.

Character Class | Matches
--- | ---
[]0-9] | any digit or ]
[aeiou^] | a vowel or ^
[-A-Z] | a dash or A - Z
[--A] | any character in the range from - to A
[aeiou-] | any vowel or -
[aei\-ou] | any vowel or -

Character classes respect the setting of the Case Sensitive checkbox in the Find & Replace dialog. For example, if Case Sensitive is on, [a] will only match "a"; if Case Sensitive is off, [a] will match both "a" and "A".

#### Matching Non-Printing Characters

As described in Chapter 7 on searching, BBEdit provides several special character pairs that you can use to match common non-printing characters, as well as the ability to specify any arbitrary character by means of its hexadecimal character code (escape code). You can use these special characters in grep patterns as well as for normal searching.

For example, to look for a tab or a space, you would use the character class [\t ] (consisting of a tab special character and a space character).

Character | Matches
--- | ---
\r | line break (carriage return)
\n | Unix line break (line feed)
\t | tab
\f | page break (form feed)
\a | alarm (hex 07)
\cX | a named control character, like \cC for Control-C
\b | backspace (hex 08) (only in character classes)
\e | Esc (hex 1B)
\xNN | hexadecimal character code NN (for example, \x0D for CR)
\x{NNNN} | any number of hexadecimal characters NN... (for example, \x{0} will match a null, \x{304F} will match a Japanese Unicode character)
\\ | backslash

Use \r to match a line break in the middle of a pattern and the special characters ^ and $ (described above) to "anchor" a pattern to the beginning of a line or to the end of a line. In the case of ^ and $, the line break character is not included in the match.

#### Other Special Character Classes

BBEdit uses several other sequences for matching different types or categories of characters.

Special Character | Matches
--- | ---
\s | any whitespace character (space, tab, carriage return, line feed, form feed)
\S | any non-whitespace character (any character not included by \s)
\w | any word character (a-z, A-Z, 0-9, _, and some 8-bit characters)
\W | any non-word character (all characters not included by \w, including carriage returns)
\d | any digit (0-9)
\D | any non-digit character (including carriage return)

A "word" is defined in BBEdit as any run of non-word-break characters bounded by word breaks. Word characters are generally alphanumeric, and some characters whose value is greater than 127 are also considered word characters.

Note that any character matched by \s is by definition not a word character; thus, anything matched by \s will also be matched by \W (but not the reverse!).

#### Quantifiers Repeat Subpatterns

The special characters * , + , and ? specify how many times the pattern preceding them may repeat. {} -style quantifiers allow you to specify exactly how many times a subpattern can repeat. The preceding pattern can be a literal character, a wildcard character, a character class, or a special character.

Pattern | Matches
--- | ---
p* | zero or more p's
p+ | one or more p's
p? | zero or one p's
p{COUNT} | match exactly COUNT p's, where COUNT is an integer
p{MIN,} | match at least MIN p's, where MIN is an integer
p{MIN, MAX} | match at least MIN p's, but no more than MAX

Note that the repetition characters * and ? match zero or more occurrences of the pattern. That means that they will always succeed, because there will always be at least zero occurrences of any pattern, but that they will not necessarily select any text (if no occurrences of the preceding pattern are present).

For this reason, when you are trying to match more than one occurrence, it is usually better to use a + than a * , because + requires a match, whereas * can match the empty string. Only use * when you are sure that you really mean "zero or more times," not just "more than once."

Try the following examples to see how their behavior matches what you expect:

Pattern | Text | Matches
--- | --- | ---
.* | Fourscore and seven years | Fourscore and seven years
[0-9]+ | I've been a loyal member since 1983 or so. | 1983
\d+ | I've got 12 years on him. | 12
A+ | BAAAAAAAB | AAAAAAA
A{3} | BAAAAB | AAA (first three A's)
A{3,} | BAAAAB | AAAA
A{1,3} | BAAAAB | AAA on the first match, the remaining A on the second match
c?andy | andy likes candy | "andy" on the first match, "candy" on the second
A+ | Ted joined AAA yesterday | "AAA" on the first match; "a" from "yesterday" on the second

#### Combining Patterns to Make Complex Patterns

So far, the patterns you have seen match a single character or the repetition of a single character or class of characters. This is very useful when you are looking for runs of digits or single letters, but often that is not enough.

However, by combining these patterns, you can search for more complex items. As it happens, you are already familiar with combining patterns. Remember the section at beginning of this discussion that said that each individual character is a pattern that matches itself? When you search for a word, you are already combining basic patterns.

You can combine any of the preceding grep patterns in the same way. Here are some examples.

Pattern | Matches | Examples
--- | --- | ---
\d+\+\d+ | a string of digits, followed by a literal plus sign, followed by more digits | 4+2 1234+5829
\d{4}[\t ]B\.C\. | four digits, followed by a tab or a space, followed by the string B.C. | 2152 B.C.
\$?[0-9,]+\.\d* | an optional dollar sign, followed by one or more digits and commas, followed by a period, then zero or more digits | 1,234.56 $4,296,459.19 $3,5,6,4.0000 0. (oops!)

Note again in these examples how the characters that have special meaning to grep are preceded by a backslash (\+, \., and \$) when we want them to match themselves.

#### Creating Subpatterns

Subpatterns provide a means of organizing or grouping complex grep patterns. This is primarily important for two reasons: for limiting the scope of the alternation operator (which otherwise creates an alternation of everything to its left and right), and for changing the matched text when performing replacements.

A subpattern consists of any simple or complex pattern, enclosed in a pair of parentheses. You can optionally specify a simple string to identify a subpattern, making it a named subpattern.

Pattern | Matches
--- | ---
(p) | the pattern p and remembers it
(?P<NAME>p) | the pattern p and remembers it by the specified string NAME

You can combine more than one subpattern into a grep pattern, or mix subpatterns and other pattern elements as you need.

Taking the last set of examples, you could modify these to use subpatterns wherever actual data appears:

Pattern | Matches | Examples
--- | --- | ---
(\d+)\+(\d+) | a string of digits, followed by a plus sign, followed by more digits | 4+2 1234+5829
(\d{4})[\t ]B\.C\. | four digits, followed by a tab or a space, followed by the string B.C. | 2152 B.C.
\$?([0-9,]+)\.(\d*) | an optional dollar sign, followed by one or more digits and commas, followed by a period, then zero or more digits | 1,234.56 $4,296,459.19 $3,5,6,4.0000 0.

#### Using Backreferences in Subpatterns

What if we wanted to match a series of digits, followed by a plus sign, followed by the exact same series of digits as on the left side of the plus? In other words, we want to match "1234+1234" or "7+7", but not "5432+1984".

Using grouping parentheses, you can do this by referring to a backreference, also known as a captured subpattern. There are two kinds of backreferences: numbered backreferences, and named backreferences. You can use both types of backreference within the same grep pattern.

Each subpattern within the complete pattern is numbered from left to right, starting with the opening parenthesis. Later in the pattern, you can refer to the text matched within any of these subpatterns by using a backslash followed by the number of that subpattern; this is a numbered backreference. Unlike numbered backreferences, which are automatically identified from the pattern, named backreferences are only available after you define them.

Pattern | Matches...
--- | ---
\1, \2, ..., \99 | the text of the nth subpattern in the entire search pattern
(?P=NAME) | the text of the subpattern NAME

Names may include alphanumeric characters and underscores, and must be unique within a pattern.

Here are some examples of numbered backreferences:

Pattern | Matches | Examples
--- | --- | ---
(\d+)\+\1 | a string of digits, followed by a plus sign, followed the same digits | 7+7 1234+1234
(\w+)\s+\1 | double words | the the
(\w)(\w)\2\1 | a word character, a second word character, followed by the second one again and the first one again | abba

We will revisit subpatterns in the section on replacement, where you will see how the choice of subpatterns affects the changes you can make.

#### Using Alternation

The alternation operator | allows you to match any of several patterns at a given point. To use this operator, place it between one or more patterns x|y to match either x or y.

As with all of the preceding options, you can combine alternation with other pattern elements to handle more complex searches.

Pattern | Text is... | Matches...
--- | --- | ---
a|t | A cat | each "a" and "t"
a|c|t | A cat | each "a", "c", and "t"
a (cat|dog) is | A cat is here. A dog is here. A giraffe is here. | "A cat is", "A dog is"
A|b+ | Abba | "A", "bb", and "a"
Andy|Ted | Andy and Ted joined AAA yesterday | "Andy" and "Ted"
\d{4}|years | I've been a loyal member since 1983, almost 16 years ago. | "1983", "years"
[a-z]+|\d+ | That's almost 16 years. | "That", "s", "almost", "16", "years"

#### The "Longest Match" Issue

###### IMPORTANT

When creating complex patterns, you should bear in mind that the quantifiers + , * , ? and {} are "greedy." That is, they will always make the longest possible match possible to a given pattern, so if your pattern is E+ (one or more E's) and your text contains "EEEE", the pattern matches all the E's at once, not just the first one. This is usually what you want, but not always.

Suppose, for instance, that you want to match an HTML tag. At first, you may think that a good way to do this would be to search for the pattern:

<.+>

consisting of a less-than sign, followed by one or more occurrences of a single character, followed by a greater-than sign. To understand why this may not work the way you think it should, consider the following sample text to be searched:

<B>This text is in boldface.</B>

The intent was to write a pattern that would match both of the HTML tags separately. Let's see what actually happens. The < character at the beginning of this line matches the beginning of the pattern. The next character in the pattern is . which matches any character (except a line break), modified with the + quantifier, taken together, this combination means one or more repetitions of any character. That, of course, takes care of the B. The problem is that the next > is also "any character" and that it also qualifies as "one or more repetitions." In fact, all of the text up to the end of the line qualifies as "one or more repetitions of any character" (the line break does not qualify, so grep stops there). After grep has reached the line break, it has exhausted the + operator, so it backs up and sees if it can find a match for >. Lo and behold, it can: the last character is a greater-than symbol. Success!

In other words, the pattern matches our entire sample line at once, not the two separate HTML tags in it as we intended. More generally, the pattern matches all the text in a given line or paragraph from the first < to the last >. The pattern only does what we intended when there is only one HTML tag in a line or paragraph. This is what we meant when we say that the regular quantifiers try to make the longest possible match.

#### Non-Greedy Quantifiers

###### IMPORTANT

To work around this "longest match" behavior, you can modify your pattern to take advantage of non-greedy quantifiers.

Quantifier | Matches...
--- | ---
+? | one or more
*? | zero or more
?? | zero or one
{COUNT}? | match exactly COUNT times
{MIN,}? | match at least MIN times
{MIN, MAX}? | match at least MIN times, but no more than MAX

Astute readers will note that these non-greedy quantifiers correspond exactly to their normal (greedy) counterparts, appended with a question mark.

Revisiting our problem of matching HTML tags, for example, we can search for:

<.+?>

This matches an opening bracket, followed by one or more occurrences of any character other than a return, followed by a closing bracket. The non-greedy quantifier achieves the results we want, preventing BBEdit from "overrunning" the closing angle bracket and matching across several tags.

A slightly more complicated example: how could you write a pattern that matches all text between <B> and </B> HTML tags? Consider the sample text below:

<B>Welcome</B> to the home of <B>BBEdit!</B>

As before, you might be tempted to write:

<B>.*</B>

but for the same reasons as before, this will match the entire line of text. The solution is similar; we will use the non-greedy *? quantifier:

<B>.*?</B>

### Writing Replacement Patterns

#### Subpatterns Make Replacement Powerful

We covered subpatterns earlier when discussing search patterns and discussed how the parentheses can be used to limit the scope of the alternation operator. Another reason for employing subpatterns in your grep searches is to provide a powerful and flexible way to change or reuse found information as part of a search-and-replace operation. If you do not use subpatterns, you can still access the complete results of the search with the & metacharacter. However, this precludes reorganizing the matched data as it is replaced.

Pattern | Inserts...
--- | ---
& | the text matched by the entire search pattern
\1, \2, ..., \99 | the text matched by the nth subpattern of the entire search pattern
\P<NAME> | the text matched by the subpattern NAME

Note

BBEdit will remember up to 99 backreferenced subpatterns. Versions prior to 6.5 were limited to 9 subpatterns.

#### Using the Entire Matched Pattern

The & character is useful when you want to use the entire matched string as the basis of a replacement. Suppose that in your text every instance of product names that begin with the company name "ACME" needs to end with a trademark symbol (?). The following search pattern finds two-word combinations that begin with "ACME":

ACME [A-Za-z]+

The following replacement string adds the trademark symbol to the matched text:

&™

For example, if you start with

ACME Magnets, ACME Anvils, and ACME TNT are all premium products.

and perform a replace operation with the above patterns, you will get:

ACME Magnets™, ACME Anvils™, and ACME TNT™ are all premium products.

#### Using Parts of the Matched Pattern

While using the entire matched pattern in a replacement string is useful, it is often more useful to use only a portion of the matched pattern and to rearrange the parts in the replacement string.

For example, suppose a source file contains C-style declarations of this type:

#define Util_Menu 284
#define Tool_Menu 295

and you want to convert them so they look like this, Pascal-style:

const int Util_Menu = 284;
const int Tool_Menu = 295;

The pattern to find the original text is straightforward:

#define[ \t]+.+[ \t]+\d+[^0-9]*$

This pattern matches the word "#define" followed by one or more tabs or spaces, followed by one or more characters of any type, followed by one or more tabs or spaces, followed by one or more digits, followed by zero or more characters that are not digits (to allow for comments), followed by the end of the line.

The problem with this pattern is that it matches the entire line. It does not provide a way to remember the individual parts of the found string.

If you use subpatterns to rewrite the above search pattern slightly, you get this:

#define[ \t]+(.+)[ \t]+(\d+)[^0-9]*$

The first set of parentheses defines a subpattern which remembers the name of the constant. The second set remembers the value of the constant.

The replacement string would look like this:

const int \1 = \2;

The sequence \1 is replaced by the name of the constant (the first subpattern from the search pattern), and the sequence \2 is replaced by the value of the constant (from the second subpattern).

Our example throws out any comment that may follow the C-style constant declaration. As an exercise, try rewriting the search and replace patterns so they preserve the comment, enclosing it in (*...*) style Pascal comment markers.

Here are some more examples:

Data | Search for | Replace | Result
--- | --- | --- | ---
4+2 | (\d+)\+(\d+) | \2+\1 | 2+4
1234+5829 | (\d+)\+(\d+) | \1+\1 | 1234+1234
2152 B.C. | (\d{4})[\t ]B\.C\. | \1 A.D. | 2152 A.D.
1,234.56 | \$?([0-9,]+)\.(\d+) | \1 dollars and \2 cents | 1,234 dollars and 56 cents
$4,296,459.19 | \$?([0-9,]+)\.(\d+) | \1 dollars and \2 cents | 4,296,459 dollars and 19 cents
$3,5,6,4.00000 | \$?([0-9,]+)\.(\d+) | \1 dollars and \2 cents | 3,5,6,4 dollars and 00000 cents

#### Case Transformations

Replace patterns can also change the case of the original text when using subpattern replacements. The syntax is similar to Perl's, specifically:

Modifier | Effect
--- | ---
\u | Make the next character uppercase
\U | Make all following characters uppercase until reaching another case specifier (\u, \L, \l ) or \E
\l | Make the next character lowercase
\L | Make all following characters lowercase until reaching another case specifier (\u, \U, \l ) or \E
\E | End case transformation opened by \U or \L

Here are some examples to illustrate how case transformations can be used.

Given some text:

mumbo-jumbo

and the search pattern:

(\w+)(\W)(\w+)

the following replace patterns will produce the following output:

\U\1\E\2\3 MUMBO-jumbo

\u\1\2\u\3 Mumbo-Jumbo

Note that case transformations also affect literal strings in the replace pattern:

\U\1\2fred MUMBO-FRED

\lMUMBLE\2\3 mUMBLE-jumbo

Finally, note that \E is not necessary to close off a modifier; if another modifier appears before an \E is encountered, that modifier will take effect immediately:

\Ufred-\uwilma FRED-Wilma

### Examples

The example patterns in this section describe some common character classes and shortcuts used for constructing grep patterns, and addresses some common tasks that you might find useful in your work.

#### Matching Identifiers

One of the most common things you will use grep patterns for is to find and modify identifiers, such as variables in computer source code or object names in HTML source documents. To match an arbitrary identifier in most programming languages, you might use this search pattern:

[a-z][a-zA-Z0-9]*

This pattern matches any sequence that begins with a lowercase letter and is followed by zero or more alphanumeric characters. If other characters are allowed in the identifier, add them to the pattern. This pattern allows underscores in only the first character of the identifier:

[a-z_][a-zA-Z0-9]*

The following pattern allows underscores anywhere but the first character, but allows identifiers to begin with an uppercase or lowercase letter:

[a-zA-Z][a-zA-Z0-9_]*

#### Matching White Space

Often you will want to match two sequences of data that are separated by tabs or spaces, whether to simply identify them, or to rearrange them.

For example, suppose you have a list of formatted label-data pairs like this:

User name: Bernard Rubble
Occupation: Actor
Spouse: Betty

You can see that there are tabs or spaces between the labels on the left and the data on the right, but you have no way of knowing how many spaces or tabs there will be on any given line. Here is a character class that means "match one or more white space characters."

[ \t]+

So, if you wanted to transform the list above to look like this:

User name("Bernard Rubble")
Occupation("Actor")
Spouse("Betty")

You would use this search pattern:

([a-z ]+):[ \t]+([a-z ]+)

and this replacement pattern:

\1\("\2"\)

#### Matching Delimited Strings

In some cases, you may want to match all the text that appears between a pair of delimiters. One way to do this is to bracket the search pattern with the delimiters, like this:

".*"

This works well if you have only one delimited string on the line. But suppose the line looked like this:

"apples", "oranges, kiwis, mangos", "penguins"

The search string above would match the entire line. (This is another instance of the "longest match" behavior of BBEdit's grep engine, which was discussed previously.)

Once again, non-greedy quantifiers come to the rescue. The following pattern will match "-delimited strings:

".+?"

#### Marking Structured Text

Suppose you are reading a long text document that does not have a table of contents, but you notice that all the sections are numbered like this:

3.2.7 Prehistoric Cartoon Communities
5.19.001 Restaurants of the Mesozoic

You can use a grep pattern to create marks for these headings, which will appear in the Mark popup menu. Choose Find & Mark All from the Mark popup menu in the navigation bar. Then, decide how many levels you want to mark. In this example, the headings always have at least two digits and at most four.

Use this pattern to find the headings:

^(\d+\.\d+\.?\d*\.?\d*)[ \t]+([a-z ]+)

and this pattern to make the file marks:

\1 \2

The ^ before the first search group ensures that BBEdit matches the numeric string at the beginning of a line. The pattern

\.?\d*

matches a (possible) decimal point and a digit sequence. The other groups use the white space idiom and the identifier idiom. You can use a similar technique to mark any section that has a section mark that can be described with grep.

#### Marking a Mail Digest

You can elaborate the structured text technique to create markers for mail digests. Assume that each digest is separated by the following lines:

From: Sadie Burke <sadie@burke.com>
Date: Sun, 16 Jul 1995 13:17:45 -0700
Subject: Fishing with the judge

Suppose you want the marker text to list the subject and the sender. You would use the following search string:

^From:[ \t]+(.*)\r.*\rSubject:[ \t]+(.*)

And mark the text with this replacement string:

\2 \1

Note that for the sequence \r.*\r in the middle of the search string, the \r before "Subject" is necessary because as previously discussed, the special character . does not match carriage returns. (At least, not by default. See "Advanced Topics," below, for details on how to make dot match any character, including carriage returns.)

#### Rearranging Name Lists

You can use grep patterns to transform a list of names in first name first form to last name first order (for a later sorting, for instance). Assume that the names are in the form:

Junior X. Potter
Jill Safai
Dylan Schuyler Goode
Walter Wang

If you use this search pattern:

^(.*) ([^ ]+)$

And this replacement string:

\2, \1

The transformed list becomes:

Potter, Junior X.
Safai, Jill
Goode, Dylan Schuyler
Wang, Walter

### Advanced Topics

BBEdit's PCRE-based grep engine offers unparalleled syntactical power. The topics below cover areas that show how grep can effectively match very complicated patterns of text--matches which were impossible to achieve with older versions of BBEdit. However, with this power comes complexity.

If you are new to grep, it is possible that the topics covered in this section will not make much sense to you. That's OK. The best way to learn grep is to use it in real life, not by reading example patterns. In many cases, the basic grep syntax covered previously in this chapter will be all that you need.

If you are an experienced user of grep, however, many of the topics covered below will be of great interest.

#### Matching Nulls

The grep engine used in versions of BBEdit prior to 6.5 was unable to search text that contained null characters (ASCII value zero), but this limitation has since been removed. Here's one way to match a null:

\x{0}

#### Backreferences

The following charts explain the rules BBEdit uses for determining backreferences.

#### In Search Patterns

Modifier | Effect
--- | ---
\0 | A backslash followed by a zero is an octal character reference. Up to two further octal characters are read. Thus, "\040" will match a space character, and "\07" will match the ASCII BEL (\x07), but "\08" will match an ASCII null followed by the digit 8 (because octal characters only range from 0-7).
\1-9 | A backslash followed by a single decimal digit from 1 to 9 is always a backreference to the Nth captured subpattern.
\10-99 | A backslash followed by two decimal digits, which taken together form the integer N (ranging from 10 to 99), is a backreference to the Nth captured subpattern, if there exist N capturing sets of parentheses in the pattern. If there are fewer than N captured subpatterns, the grep engine will instead look for up to three octal digits following the backslash. Any subsequent digits stand for themselves. So, in a search pattern, "\11" is a backreference if there are 11 or more sets of capturing parentheses in the pattern. If not, it matches a tab. "\011" always matches a tab. "\81" is a backreference if there are 81 or more captured subpatterns, but matches an ASCII null followed by the two characters "8" and "1" otherwise.

#### In Character Classes

Modifier | Effect
--- | ---
\OCTAL | Inside a character class, a backslash followed by up to three octal digits generates a single byte character reference from the least significant eight bits of the value. Thus, the character class "[\7]" will match a single byte with octal value 7 (equivalent to "\x07"). "[\8]" will match a literal "8" character.

#### In Replacement Patterns

Modifier | Effect
--- | ---
\NNN+ | If more than two decimal digits follow the backslash, only the first two are considered part of the backreference. Thus, "\111" would be interpreted as the 11th backreference, followed by a literal "1". You may use a leading zero; for example, if in your replacement pattern you want the first backreference followed by a literal "1", you can use "\011". (If you use "\11", you will get the 11th backreference, even if it is empty.)
\NN | If two decimal digits follow the backslash, which taken together represent the value N, and if there is an Nth captured substring, then all three characters are replaced with that substring. If there is not an Nth captured substring, all three characters are discarded--that is, the backreference is replaced with the empty string.
\N | If there is only a single digit N following the backslash and there is an Nth captured substring, both characters are replaced with that substring. Otherwise, both characters are discarded--that is, the backreference is replaced with the empty string. In replacement patterns, \0 is a backreference to the entire match (exactly equivalent to "&").

#### POSIX-Style Character Classes

BBEdit now provides support for POSIX-style character classes. These classes are used in the form [:CLASS:] , and are only available inside regular character classes (in other words, inside another set of square brackets).

Class | Meaning
--- | ---
alnum | letters and digits
alpha | letters
ascii | character codes 0-127
blank | horizontal whitespace
cntrl | control characters
digit | decimal digits (same as \d)
graph | printing characters, excluding spaces
lower | lower case letters
print | printing characters, including spaces
punct | punctuation characters
space | white space (same as \s)
upper | upper case letters
word | "word" characters (same as \w)
xdigit | hexadecimal digits

For example: [[:digit:]]+ is the same as: [\d]+

POSIX-style character class names are case-sensitive.

It is easy to forget that POSIX-style character classes are only available inside regular character classes. The pattern [:space:] , without enclosing square brackets, is just a character class consisting of the characters ":", "a", "c", "e", "p", and "s".

The names "ascii" and "word" are Perl extensions; the others are defined by the POSIX standard. Another Perl extension supported by BBEdit is negated POSIX-style character classes, which are indicated by a ^ after the colon. For example, to match any run of non-digit characters:

[[:^digit:]]+

#### Non-Capturing Parentheses

As described in the preceding section "Creating Subpatterns", bare parentheses cluster and capture the subpatterns they contain. The portion of the matching pattern contained within the first pair of parentheses is available in the backreference \1, the second in \2, and so on.

Opening parentheses are counted from left to right to determine the numbers of the captured subpatterns. For example, if the following grep pattern:

((red|white) (king|queen))

is matched against the text "red king", the backreferences will be set as follows:

\1 "red king"

\2 "red"

\3 "king"

Sometimes, however, parentheses are needed only for clustering, not capturing. BBEdit now supports non-capturing parentheses, using the syntax:

(?:PATTERN)

That is, if an open parenthesis is followed by "?:", the subpattern matched by that pair of parentheses is not counted when computing the backreferences. For example, if the text "red king" is matched against the pattern:

(?:(red|white) (king|queen))

the backreferences will be set as follows:

\1 "red"
\2 "king"

#### Perl-Style Pattern Extensions

BBEdit's grep engine supports several extended sequences, which provide grep patterns with super-powers from another universe. Their syntax is in the form:

(?KEY...)

in other words, an open parenthesis followed by a question mark, followed by a KEY for the particular grep extension, followed by the rest of the subpattern and a closing parenthesis. This syntax--specifically, an open parenthesis followed by a question mark--was not valid in older versions of BBEdit, thus, none of these extensions will conflict with old patterns.

We have already seen one such extension in the previous section of this document--non-capturing parentheses: (?:...). The remainder are listed in the chart below, and discussed in detail afterward.

Extension | Meaning
--- | ---
(?:...) | Cluster-only parentheses, no capturing
(?#...) | Comment, discard all text between the parentheses
(?imsx-imsx) | Enable/disable pattern modifiers
(?imsx-imsx:...) | Cluster-only parens with modifiers
(?=...) | Positive lookahead assertion
(?!...) | Negative lookahead assertion
(?<=...) | Positive lookbehind assertion
(?<!...) | Negative lookbehind assertion
(?()...|...) | Match with if-then-else
(?()...) | Match with if-then
(?>...) | Match non-backtracking subpattern ("once-only")
(?R) | Recursive pattern

#### Comments

The sequence (?# marks the start of a comment which continues up to the next closing parenthesis. Nested parentheses are not permitted. The characters that make up a comment play no part in the pattern matching at all.

Search for: foo(?# Hello, this is a comment)bar
Will match: foobar

#### Pattern Modifiers

The settings for case sensitivity, multi-line matching, whether the dot character can match returns, and "extended syntax" can be turned on and off within a pattern by including sequences of letters between "(?" and ")".

Modifier | Meaning | Default
--- | --- | ---
i | case insensitive | according to Case Sensitive checkbox in Find & Replace dialog
m | allow ^ and $ to match at \r | on
s | allow . to match \r | off
x | ignore most white space and allow inline comments in grep patterns | off

i -- By default, BBEdit obeys the "Case Sensitive" checkbox in the Find & Replace dialog (or the corresponding property of the search options when using the scripting interface). The (?i) option overrides this setting.

m -- By default, BBEdit's grep engine will match the ^ and $ metacharacters after and before returns, respectively. If you turn this option off with (?-m) , ^ will only match at the beginning of the document, and $ will only match at the end of the document. (If that is what you want, however, you should consider using the new \A, \Z, and \z metacharacters instead of ^ and $.)

s -- By default, the magic dot metacharacter . matches any character except return ("\r"). If you turn this option on with (?s) , however, dot will match any character. Thus, the pattern (?s).+ will match an entire document.

x -- When turned on, this option changes the meaning of most whitespace characters (notably, tabs and spaces) and #. Literal whitespace characters are ignored, and the # character starts a comment that extends until a literal return or the "\r" escape sequence is encountered. Ostensibly, this option intends to let you write more "readable" patterns.

Perl programmers should already be familiar with these options, as they correspond directly to the -imsx options for Perl's m// and s/// operators. Unadorned, these options turn their corresponding behavior on; when preceded by a hyphen (-), they turn the behavior off. Setting and unsetting options can occur in the same set of parentheses.

Example | Effect
--- | ---
(?imsx) | Turn all four options on
(?-imsx) | Turn all four options off
(?i-msx) | Turn "i" on, turn "m", "s", and "x" off

The scope of these option changes depends on where in the pattern the setting occurs. For settings that are outside any subpattern, the effect is the same as if the options were set or unset at the start of matching. The following patterns all behave in exactly the same way:

(?i)abc

a(?i)bc

ab(?i)c

abc(?i)

In other words, all four of the above patterns will match without regard to case. Such "top level" settings apply to the whole pattern (unless there are other changes inside subpatterns). If there is more than one setting of the same option at the top level, the right-most setting is used.

If an option change occurs inside a subpattern, the effect is different. An option change inside a subpattern affects only that part of the subpattern that follows it, so, if the "Case Sensitive" checkbox is turned on:

Search for: (a(?i)b)c

Will match: abc or aBc

and will not match anything else. (But if "Case Sensitive" is turned off, the "(?i) " in the above pattern is superfluous and has no effect.) By this means, options can be made to have different settings in different parts of the pattern. Any changes made in one alternative do carry on into subsequent branches within the same subpattern. For example:

Search for: (a(?i)b|c)

matches "ab", "aB", "c", and "C", even though when matching "C", the first branch is abandoned before the option setting.

These options can also be set using the clustering (non-capturing) parentheses syntax defined earlier, by inserting the option letters between the "?" and ":". The scope of options set in this manner is limited to the subpattern contained therein. Examples:

Search for: (?i:saturday|sunday)

Will match: SATURDAY or Saturday or SUNday (and so on)

Search for: (?i:foo)(?-i:bar)

Will match: foobar or FOObar

Will not match: FOOBAR or fooBAR

#### Positional Assertions

Positional assertions "anchor" a pattern, without actually matching any characters. Simple assertions have already been described: those which are invoked with the escape sequences \b, \B, \A, \Z, \z, ^ and $. For example, the pattern \bfoo\b will only match the string "foo" if it has word breaks on both sides, but the \b's do not themselves match any characters; the entire text matched by this pattern are the three characters "f", "o", and "o".

Lookahead and lookbehind assertions work in a similar manner, but allow you to test for arbitrary patterns to anchor next to. If you have ever said to yourself, "I would like to match `foo', but only when it is next to `bar'," lookaround assertions fill that need.

Positive lookahead assertions begin with "(?= ", and negative lookahead assertions begin with "(?! ". For example:

\w+(?=;)

will match any word followed by a semicolon, but the semicolon is not included as part of the match.

foo(?!bar)

matches any occurrence of "foo" that is not followed by "bar". Note that the apparently similar pattern:

(?!foo)bar

does not find an occurrence of "bar" that is preceded by something other than "foo"; it finds any occurrence of "bar" whatsoever, because the assertion (?!foo) is always true when the next three characters are "bar". A lookbehind assertion is needed to achieve this effect.

Positive lookbehind assertions start with "(?<= ", and negative lookbehind assertions start with "(?<! ". For example:

(?<!foo)bar

does find an occurrence of "bar" that is not preceded by "foo". The contents of a lookbehind assertion are restricted such that all the strings it matches must have a fixed length. However, if there are several alternatives, they do not all have to have the same fixed length. Thus

(?<=Martin|Lewis)

is permitted, but

(?<!dogs?|cats?)

causes an error. Branches that match different length strings are permitted only at the top level of a lookbehind assertion. This is different compared with Perl 5.005, which requires all branches to match the same length of string. An assertion such as

(?<=ab(c|de))

is not permitted, because its single top-level branch can match two different lengths, but it is acceptable if rewritten to use two top-level branches:

(?<=abc|abde)

The implementation of lookbehind assertions is, for each alternative, to temporarily move the current position back by the fixed width and then try to match. If there are insufficient characters before the current position, the match is deemed to fail. (Lookbehinds in conjunction with non-backtracking [a.k.a. "once-only"] subpatterns can be particularly useful for matching at the ends of strings; an example is given in the section on once-only subpatterns below.)

Several assertions (of any sort) may occur in succession. For example,

(?<=\d{3})(?<!999)foo

matches "foo" preceded by three digits that are not "999". Notice that each of the assertions is applied independently at the same point in the subject string. First there is a check that the previous three characters are all digits, and then there is a check that the same three characters are not "999". This pattern does not match "foo" preceded by six characters, the first of which are digits and the last three of which are not "999". For example, it does not match "123abcfoo". A pattern to do that is:

(?<=\d{3}...)(?<!999)foo

This time the first assertion looks at the preceding six characters, checking that the first three are digits, and then the second assertion checks that the preceding three characters are not "999". Assertions can be nested in any combination. For example,

(?<=(?<!foo)bar)baz

matches an occurrence of "baz" that is preceded by "bar" which in turn is not preceded by "foo", while

(?<=\d{3}(?!999)...)foo

is another pattern which matches "foo" preceded by three digits and any three characters that are not "999".

Assertion subpatterns are not capturing subpatterns, and may not be repeated, because it makes no sense to assert the same thing several times. If any kind of assertion contains capturing subpatterns within it, these are counted for the purposes of numbering the capturing subpatterns in the whole pattern. However, substring capturing is carried out only for positive assertions, because it does not make sense for negative assertions.

#### Conditional Subpatterns

Conditional subpatterns allow you to apply "if-then" or "if-then-else" logic to pattern matching. The "if" portion can either be an integer between 1 and 99, or an assertion.

The forms of syntax for an ordinary conditional subpattern are:

if-then: (?(condition)yes-pattern)

if-then-else: (?(condition)yes-pattern|no-pattern)

and for a named conditional subpattern are:

if-then: (?P<NAME>(condition)yes-pattern)

if-then-else: (?P<NAME>(condition)yes-pattern|no-pattern)

If the condition evaluates as true, the "yes-pattern" portion attempts to match. Otherwise, the "no-pattern" portion does (if there is a "no-pattern").

If the "condition" text between the parentheses is an integer, it corresponds to the backreferenced subpattern with the same number. (Do not precede the number with a backslash.) If the corresponding backreference has previously matched in the pattern, the condition is satisfied. Here's an example of how this can be used. Let's say we want to match the words "red" or "blue", and refer to whichever word is matched in the replacement pattern. That's easy:

(red|blue)

To make it harder, let's say that if (and only if) we match "blue", we want to optionally match a space and the word "car" if they follow directly afterward. In other words, we want to match "red", "blue", or if possible, "blue car", but we do not want to match "red car". We cannot use the pattern:

(red|blue)( car)?

because that will match "red car". Nor can we use:

(red|blue car|blue)

because in our replacement pattern, we want the backreference to only contain "red" or "blue", without the " car". Using a conditional subpattern, however, we can search for:

((blue)|(red))(?(2) car)?

Here's how this pattern works. First, we start with "((blue)|(red)) ". When this subpattern matches "blue", \1 and \2 are set to "blue", and \3 is empty. When it matches "red", \1 and \3 are set to "red", and \2 is empty.

Next comes the conditional subpattern "(?(2) car)? ". The conditional test is on "2", the second backreferenced subpattern: if \2 is set, which in our case means it has matched the word "blue", then it will try to match " car". If \2 is not set, however, the entire conditional subpattern is skipped. The question mark at the end of the pattern makes this conditional match optional, even if \2 is set to "blue".

Here's an example that uses an assertion for the condition, and the if-then-else form. Let's say we want to match a run of digits of any length, followed by either " is odd" or " is even", depending on whether the matched digits end with an odd or even digit.

\d+(?(?<=[13579]) is odd| is even)

This pattern starts with "\d+" to match the digits. Next comes a conditional subpattern, with a positive lookbehind assertion as the condition to be satisfied. The lookbehind assertion is true only if the last character matched by \d+ was also in the character class [13579]. If that is true, we next try to match " is odd"; if it is not, we try to match " is even". Thus, this pattern will match "123 is odd", "8 is even", and so on, but will not match "9 is even" or "144 is odd".

#### Once-Only Subpatterns

With both maximizing (greedy) and minimizing (non-greedy) repetition, failure of what follows normally causes the repeated item to be reevaluated to see if a different number of repeats allows the rest of the pattern to match. Sometimes it is useful to prevent this, either to change the nature of the match, or to cause it to fail earlier than it otherwise might, when the author of the pattern knows there is no point in carrying on.

Consider, for example, the pattern "\d+foo " when matching against the text "123456bar".

After matching all 6 digits and then failing to match "foo", the normal action of the grep engine is to try again with only 5 digits matching the \d+ item, and then with 4, and so on, before ultimately failing. Once-only subpatterns provide the means for specifying that once a portion of the pattern has matched, it is not to be reevaluated in this way, so the matcher would give up immediately on failing to match "foo" the first time. The notation is another kind of special parenthesis, starting with "(?> ", as in this example:

(?>\d+)bar

This kind of parentheses "locks up" the part of the pattern it contains once it has matched, and a failure further into the pattern is prevented from backtracking into it. Backtracking past it to previous items, however, works as normal.

In most situations, such as in the example above, the time saved by using once-only subpatterns is insignificant--a few small fractions of a second, at most. With some complicated grep patterns or with humongous lines of text, however, you can save tremendous amounts of time using once-only subpatterns.

Once-only subpatterns are not capturing subpatterns. Simple cases such as the above example can be thought of as a maximizing repeat that must swallow everything it can. So, while both \d+ and \d+? are prepared to adjust the number of digits they match in order to make the rest of the pattern match, (?>\d+) can only match an entire sequence of digits.

Once-only subpatterns can be used in conjunction with lookbehind assertions to specify efficient matching at the end of a line of text. Consider a simple pattern such as:

abcd$

when applied to a long line of text which does not match (in other words, a long line of text that does not end with "abcd"). Because matching proceeds from left to right, the grep engine will look for each "a" in the subject and then see if what follows matches the rest of the pattern. If the pattern is specified as:

^.*abcd$

the initial .* matches the entire line at first, but when this fails (because there is no following "a"), it backtracks to match all but the last character, then all but the last two characters, and so on. Once again the search for "a" covers the entire string, from right to left, so we are no better off. However, if the pattern is written as:

^(?>.*)(?<=abcd)

there can be no backtracking for the .* item; it can match only the entire line. The subsequent lookbehind assertion does a single test on the last four characters. If it fails, the whole match fails immediately. For long strings, this approach makes a significant difference to the processing time.

When a pattern contains an unlimited repeat inside a subpattern that can itself be repeated an unlimited number of times, the use of a once-only subpattern is the only way to avoid some failing matches taking a very long time (literally millions or even billions of years, in some cases!). The pattern:

(\D+|<\d+>)*[!?]

matches an unlimited number of substrings that either consist of non-digits, or digits enclosed in <>, followed by either ! or ?. When it matches, it runs quickly. However, if it is attempts to match this line of text:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

it takes a long time before reporting failure. So long, in fact, that it will effectively "freeze" BBEdit. This is not really a crash, per se, but left to run on its own, it might take years before it finally fails. (We are not sure, frankly, because much like determining how many licks it takes to get to the center of a Tootsie Pop, we do not feel like waiting long enough to find out.)

The reason this takes so long to fail is because the string can be divided between the two repeats in a large number of ways, and all have to be tried before the grep engine knows for certain that the pattern will not match. (The example used [!?] rather than a single character at the end, because both PCRE and Perl have an optimization that allows for fast failure when a single character is used. They remember the last single character that is required for a match, and fail early if it is not present in the string.) If the pattern is changed to

((?>\D+)|<\d+>)*[!?]

sequences of non-digits cannot be broken, and failure happens quickly.

#### Recursive Patterns

Consider the problem of matching a string in parentheses, allowing for unlimited nested, balanced parentheses. Without the use of recursion, the best that can be done is to use a pattern that matches up to some fixed depth of nesting. It is not possible to handle an arbitrary nesting depth. Perl 5.6 has provided an experimental facility that allows regular expressions to recurse (among other things). It does this by interpolating Perl code in the expression at run time, and the code can refer to the expression itself. Obviously, BBEdit's grep engine cannot support the interpolation of Perl code. Instead, the special item (?R) is provided for the specific case of recursion. The following recursive pattern solves the parentheses problem:

\(((?>[^()]+)|(?R))*\)

First it matches an opening parenthesis. Then it matches any number of substrings which can either be a sequence of non-parentheses, or a recursive match of the pattern itself (that is, a correctly parenthesized substring). Finally there is a closing parenthesis.

This particular example pattern contains nested unlimited repeats, and so the use of a once-only subpattern for matching strings of non-parentheses is important when applying the pattern to strings that do not match. For example, when it tries to match against this line of text:

(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()

it yields "no match" quickly. However, if a once-only subpattern is not used, the match runs for a very long time indeed because there are so many different ways the + and * repeats can carve up the subject, and all have to be tested before failure can be reported.

### Recommended Resources

Our company bookshelf contains information about other books that you may find useful. We list one in particular here:

#### Mastering Regular Expressions, 3rd Edition

by Jeffrey E.F. Friedl. O'Reilly & Associates, 2006. ISBN 0-596-52812-4

Although it does not cover BBEdit's grep features specifically, Mastering Regular Expressions is an outstanding resource for learning the "how-to" of writing useful grep patterns, and the latest edition is even better than the original.

#### BBEdit Talk

The BBEdit Talk discussion group covers a wide range of topics and questions about using BBEdit, which frequently include searching and the use of grep patterns.

http://groups.google.com/group/bbedit