Mastering grep in Linux: Search Text, Regex, and Filter Files
The grep command on Linux is widely used in day-to-day administrative tasks on Linux. It filters the lines of a given file searching for a regular expression as a pattern.
Grep can read one or more files that are passed as arguments, or it can receive on standard input the redirection of the output from another process. If grep receives more than one file or a wildcard as an argument to perform its search, it will indicate the filename followed by a colon and the matching line.
Grep uses the POSIX BRE POSIX BRE regular expression pattern.
Thus, the meta-characters ? + { } | ( ) do not have special meaning. In the BRE pattern, these characters are only interpreted with special meaning if preceded by a backslash \? \+ \{ \} \| \( \).
Its most frequent options are:
- -c: Shows only the count of occurrences in the files and not the lines where the occurrences were found;
- -h: Shows only the matching lines, without indicating the filenames;
- -i: Searches for occurrences ignoring whether the letters are uppercase or lowercase;
- -v: Shows all lines of the searched file except the matching occurrences. It has the reverse effect;
- -n: Shows, in addition to the text of the matching lines, the line numbers within the files;
- -B n: Shows n lines before the matching line;
- -A n: Shows n lines after the matching line.
- -E Changes the POSIX BRE pattern to POSIX ERE.
- -F Does not interpret any meta-characters
Examples:
Searches for the word uira in the /etc/passwd file:
$ grep uira /etc/passwduira:x:500:100:uira:/home/uira:/bin/bash
Searches for all lines starting with the letter u in the /etc/passwd file. The caret symbol represents the beginning of a line:
$ grep "^u" /etc/passwduucp:x:10:14:Unix-to-Unix CoPy system:/etc/uucp:/bin/bashuira:x:500:100:uira:/home/uira:/bin/bash
Searches for all lines ending with the word false. The $ symbol represents the end of a line:
$ grep "false$" /etc/passwdmail:x:8:12:Mailer daemon:/var/spool/clientmqueue:/bin/falsewwwrun:x:30:8:WWW daemon apache:/var/lib/wwwrun:/bin/false
Searches for all lines beginning with vowels in /etc/passwd. The regular expression called bracket expression searches for any of the characters inside the brackets:
$ grep "^[aeiou]" /etc/passwduucp:x:10:14:Unix-to-Unix CoPy system:/etc/uucp:/bin/bashat:x:25:25:Batch jobs daemon:/var/spool/atjobs:/bin/bashuira:x:500:100:uira:/home/uira:/bin/bashalias:x:501:1000::/var/qmail:/bin/false
Searches for all lines where the first character is any character and the second character is a vowel. The dot in the regular expression symbolizes "any single character":
$ grep "^.[aeiou]" /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/bin/bashnews:x:9:13:News system:/etc/news:/bin/bashuira:x:500:100:uira:/home/uira:/bin/bash
Searches for lines containing a sequence of at least four consecutive numbers:
$ grep "[0-9][0-9][0-9][0-9]" /etc/passwdsquid:x:31:65534:WWW-proxy squid:/var/cache/squid:/bin/falsenobody:x:65534:65533:nobody:/var/lib/nobody:/bin/bashalias:x:501:1000::/var/qmail:/bin/falseqmaild:x:502:1000::/var/qmail:/bin/false
Searches in all files in a directory for the occurrence of the word security.
$ grep security *
View the dates file:
$ cat datas1978-05-11 João 1976-02-23 Maria2001-07-11 Pedro1980-05-14 Carla
To search for people born on the 11th using grep, you must indicate that the characters { } are metacharacters using the backslash:
$ grep "^[0-9]\{4\}-[0-9]\{2\}-11" datas
1978-05-11 João
2001-07-11 Pedro
To search for an occurrence in all subdirectories, use the recursive option "-r":
$ grep -r uira *
To invert a search (bring all occurrences except for a specific term, use the "-v" option.
In this example, it returns all non-commented lines from php.ini:
$ grep -v "^;" /etc/php.ini
To list only lines with valid email addresses:
$ grep -o '[[:alnum:]+\.\_\-]*@[[:alnum:]+\.\_\-]*' emails.txt
To list all unique IP addresses that accessed a web server:
$ grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" /var/log/nginx/access.log | sort | uniq
It is also possible to use expressions with OR to search for more than one term:
$ grep -E 'carla|uira' arquivo
It is worth remembering that grep is case-sensitive. To perform a search regardless of whether the text is in uppercase or lowercase, you can use the "-i" option:
$ grep -i uira *
Searches with the "-i" option take longer.
It is possible to use brackets to specify occurrences of some search character in uppercase or lowercase:
$ grep [Uu]ira *
To show the line of a specific occurrence:
$ grep -n uira arquivo
To show one line before and after the term, you can use the "-C N" option, where N is the number of lines:
$ grep -C 1 function LivroSubcapituloList.php
public static function onChangeLivro($param = null)
{
Egrep command
The egrep command works like the -E option of grep.
It actually uses the POSIX ERE regular expression pattern in the search. This means that the backslash must be used to define that the next character is a literal character and not a metacharacter like in the POSIX BRE pattern.
This means that the characters ? + { } | ( ) do not need the backslash to function as metacharacters.
Take the birthday list as an example. With the grep command and without backslashes, grep is not able to find the birthday people in May:
$ grep "^[0-9]{4}-05-[0-9]{2}" datas
However, egrep is able to interpret { } as metacharacters without the backslash. It is important that you remember the difference in the use of backslashes between grep (which needs them to indicate metacharacters) and egrep (whose effect of backslashes is reversed, indicating a literal character):
$ egrep "^[0-9]{4}-05-[0-9]{2}" datas1978-05-11 João 1980-05-14 Carla
Only with the -E option is grep able to find the occurrences:
$ grep -E "^[0-9]{4}-05-[0-9]{2}" datas1978-05-11 João 1980-05-14 Carla
It is very important that you know what the backslash does in the POSIX BRE vs POSIX ERE pattern.
Fgrep command
The fgrep command is also similar to grep, but it does not support regular expressions, searching only for a search pattern or plain text in the files.
For this reason, it is faster than grep, but less versatile.
It is the same as the -F option of grep.
Example:
$ fgrep batata *listaab:batatasupermercado:batata
Learn much more about Linux in our online course. You can enroll here. If you already have an account, or want to create one, just log in or create your user here.
Did you like it? Share
That was just one piece. The course teaches the whole path — from your first command to exam day.