1. Overview

Matching a pattern along with n characters before and after it can be useful in situations where we need to locate specific patterns within large text files or groups of files. For example, when analyzing system logs, extracting an error message pattern along with its context can help identify the source of the error. Similarly, locating a specific pattern along with a finite number of characters around it can be helpful when analyzing genome sequences.

In this tutorial, we’ll learn how to extract a pattern and the n characters preceding and following it.

2. Extracting a Pattern and Its Context

To extract a pattern and its surrounding context, we may use regular expressions (regex) along with the grep command.

Let’s first inspect the content of a test file we’ll be using:

$ cat file.txt
hello
abcdefghijklmnopqrstuvwxyz
the quick brown fox jumps over the lazy dog

The file contains three lines. We’ll try to match specific patterns within the file along with the surrounding n characters.

Let’s now look at the tools we need to do so.

2.1. Regular Expressions

Regular expressions are a powerful tool for matching patterns in text. They consist of a combination of characters and symbols that represent specific patterns. For example, the dot (.) symbol matches any single character except a newline character, and {min,max} matches the preceding character or pattern at least min times but no more than max times.

Here’s a list of a few regex quantifiers:

Syntax

Explanation

{min,}

Match the preceding character or pattern min or more times

{,max}

Match the preceding character or pattern max or fewer times

{min,max}

Match the preceding character or pattern between min and max times, inclusively

.

Match any single character except a newline character

By using regular expressions, we can specify the pattern we want to match, along with the characters that should come before and after it.

2.2. Matching a Pattern With grep

The grep command scans through a file or input stream to find lines that match a given pattern.

Let’s then look at an example using file.txt:

$ grep -o 'el\{0,2\}o' file.txt
ello

The -o option outputs only the matching part of the line instead of the whole line. The letter l is to be matched between zero and twice at most. Basic and extended regular expressions in Bash are generally greedy. That is, the longest possible string will be matched, which in this case consists of two l letters.

We may shorten the syntax in the previous example using extended regex:

$ grep -oE 'el{,2}o' file.txt
ello

The -E option enables extended regular expressions, which provide additional features for matching patterns. In this case, it allows us to use the braces without having to escape these with a backslash. We’ve also removed the lower bound, which is zero because there is no need to specify it explicitly.

3. Extracting “n” Characters Around a Matched Pattern

We may also use grep and regular expressions to match a pattern along with n characters before and after it. However, we should distinguish here between the two cases.

The first case consists of extracting up to n characters on either side of the matched pattern. This means that a result is still possible even if the matched pattern is not surrounded by the specified number of characters.

The second case consists of extracting exactly n characters before and after the matched pattern, so there must necessarily be n characters on both sides of the pattern for a successful match.

3.1. Extracting up to “n” Characters Around a Pattern

Let’s use grep and regular expressions to extract up to five characters on either side of the pattern, rst:

$ grep -oE '.{,5}rst.{,5}' file.txt
mnopqrstuvwxy

Here, the dot (.) symbol matches any character, and the {,5} notation following it specifies that there should be at most five occurrences of such characters. Therefore, the pattern in the command will match any sequence of characters that contains the specified pattern, rst, along with five characters before and after it.

Now, what happens if the pattern is not bounded by enough characters on either side?

Let’s suppose the pattern to match this time is cde:

$ grep -oE '.{,5}cde.{,5}' file.txt
abcdefghij

Here, we see that only two characters precede the pattern, and five follow it. Therefore, as expected, the result will show up to five characters surrounding the pattern on either side.

3.2. Extracting Exactly “n” Characters Around a Pattern

Now, if we try to match the pattern, cde, with exactly five characters before and after it, the matching will not yield any result:

$ grep -oE '.{5}cde.{5}' file.txt

This returns a null string because there is no matching pattern in file.txt that consists of five characters followed by cde and another five characters.

3.3. Parameterizing the Regular Expression

For greater flexibility, we may parameterize the input variables used in the regular expression.

For example, let’s set the pattern and the number of characters, n, as variables:

$ pattern='fox'
$ n=6
$ grep -oE ".{,$n}${pattern}.{,$n}" file.txt
brown fox jumps

This gives the matched pattern, fox, along with six characters on each side. We’ve used double quotes, in this case, to allow for the expansion of the variables.

3.4. Extracting Asymmetric Context Around a Pattern

Finally, we can extract a different number of characters on either side of the pattern:

$ pattern='fox'
$ grep -oE ".{,12}${pattern}.{,6}" file.txt
quick brown fox jumps

This shows twelve characters preceding the pattern, fox, and six characters following it.

4. Conclusion

In this article, we learned that matching a pattern along with n characters before and after it in Bash can be achieved using regular expressions and grep. By using these tools, we can quickly search for specific patterns within large text files, making it a powerful technique for text processing and analysis.