Many Unix utilities use regular expressions to specify patterns. Before we go into actual examples of regular expressions, let's define a few terms and explain a few conventions that I will use in the exercises.
Character any printable symbol, such as a letter, number, or punctuation mark.
String a sequence of characters, such as cat or segment (sometimes referred to as a literal).
Expression also a sequence of characters. The difference between a string and an expression is that while strings are to be taken literally, expressions must be evaluated before their actual value can be determined. (The manual page for GNU grep compares regular expressions to mathematical expressions.) An expression usually can stand for more than one thing, for example the regular expression th[ae]n can stand for then or than. Also, the shell has its own type of expression, called globbing, which is usually used to specify file names. For example, *.c matches any file ending in the characters .c.
Metacharacters the characters whose presence turns a string into an expression. Metacharacters can be thought of as the operators that determine how expressions are evaluated. This will become more clear as we work through the examples below.
You have probably entered a shell command like
$ ls -l *.c
at some time. The shell “knows” that it is supposed to replace *.c with a list of all the files in the current directory whose names end in the characters .c.
This gets in the way if we want to pass a literal * (or ?, |, $, etc.) character to grep. Enclosing the regular expression in `single quotes' will prevent the shell from evaluating any of the shell's metacharacters. When in doubt, enclose your regular expression in single quotes.
The most basic regular expression is simply a string. Therefore a string such as foo is a regular expression that has only one match: foo.
We'll continue our examples with another file in the same directory, so make sure you are still in the /usr/src/linux directory:
$ grep Linus CREDITS
Linus N: Linus Torvalds E: Linus.Torvalds@Helsinki.FI D: Personal information about Linus
This quite naturally gives the four lines that have Linus Torvalds' name in them.
As I said earlier, the Unix shells have different metacharacters, and use different kinds of expressions. The metacharacters . and * cause the most confusion for people learning regular expression syntax after they have been using shells (and DOS, for that matter).
In regular expressions, the character . acts very much like the ? at the shell prompt: it matches any single character. The *, by contrast, has quite a different meaning: it matches zero or more instances of the previous character.
If we type
$ grep tha. CREDITS
we get this (partial listing only):
S: Northampton E: Hein@Informatik.TU-Clausthal.de
As you can see, grep printed every instance of tha followed by any character. Now try
$ grep 'tha*' CREDITS S: Northampton D: Author of serial driver D: Author of the new e2fsck D: Author of loopback device driver
We received a much larger response with “*”. Since “*” matches zero or more instances of the previous character (in this case the letter “a”), we greatly increase our possibility of a match because we made th a legal match!
One of the most powerful constructs available in regular expression syntax is the character class. A character class specifies a range or set of characters to be matched. The characters in a class are delineated by the [ and ] symbols. The class [a-z] matches the lowercase letters a through z, the class [a-zA-Z] matches all letters, uppercase or lowercase, and [Lh] would match upper case L or lower case h.
$ grep 'sm[ai]' CREDITS E: firstname.lastname@example.org D: Author of several small utilities
since our expression matches sma or smi. The command
$ grep '[a-z]' CREDITS
gives us most of the file. If you look at the file closely, you'll see that a few lines have no lowercase letters; these are the only lines that grep does not print.
Now since we can match a set of characters, why not exclude them instead? The circumflex, ^, when included as the first member of a character class, matches any character except the characters specified in the class.
$ grep Sm CREDITS
gives us three lines:
D: Small patches for kernel, libc D: Smail binary packages for Slackware and Debian N: Chris Smith $ grep 'Sm[^i]' CREDITS
gives us two
D: Small patches for kernel, libc D: Smail binary packages for Slackware and Debian
because we excluded i as a possible letter to follow Sm.
To search for a class of characters including a literal ^ character, don't place it first in the class. To search for a class including a literal -, place it the very last character of the class. To search for a class including the literal character ], place it the first character of the class.
Often it is convenient to base searches on the position of the characters on a line. The ^ character matches the beginning of a line (outside of a character class, of course) and the $ matches the end. (Users of vi may recognize these metacharacters as commands.) Earlier, searching for Linus gave us four lines. Let's change that to:
grep 'Linus$' CREDITS
which gives us
Linus D: Personal information about Linus
two lines, since we specified that Linus must be the last five characters of the line. Similarly,
grep - CREDITS
produces 99 lines, while
grep '^-' CREDITS
produces only one line:
In some circumstances you may need to match a metacharacter. Inside a character class set all characters are taken as literals (except ^, -, and ], as shown above). However, outside of classes we need a way to turn a metacharacter into a literal character to match.
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?
|Using Salt Stack and Vagrant for Drupal Development||May 20, 2013|
|Making Linux and Android Get Along (It's Not as Hard as It Sounds)||May 16, 2013|
|Drupal Is a Framework: Why Everyone Needs to Understand This||May 15, 2013|
|Home, My Backup Data Center||May 13, 2013|
|Non-Linux FOSS: Seashore||May 10, 2013|
|Trying to Tame the Tablet||May 08, 2013|
- RSS Feeds
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- New Products
- Validate an E-Mail Address with PHP, the Right Way
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Download the Free Red Hat White Paper "Using an Open Source Framework to Catch the Bad Guy"
- Tech Tip: Really Simple HTTP Server with Python
- New Products
- Android is Linux -- why no better inter-operation
2 hours 7 min ago
- Connecting Android device to desktop Linux via USB
2 hours 36 min ago
- Find new cell phone and tablet pc
3 hours 34 min ago
5 hours 3 min ago
- Automatically updating Guest Additions
6 hours 11 min ago
- I like your topic on android
6 hours 58 min ago
- Reply to comment | Linux Journal
7 hours 19 min ago
- This is the easiest tutorial
13 hours 34 min ago
- Ahh, the Koolaid.
19 hours 12 min ago
- git-annex assistant
1 day 1 hour ago