10

I'm learning bash code and today I'm studying the command grep.

if I run

$ ps -fU user | grep thunderbird

terminal shows:

user  17410     1  0 10:09 ?        00:00:20 /usr/lib/thunderbird/thunderbird
user  18990 15896  0 12:25 pts/1    00:00:00 grep --color=auto thunderbird

But if I run:

$ ps -fU user | grep [t]hunderbird

terminal shows:

user  17410     1  0 10:09 ?        00:00:20 /usr/lib/thunderbird/thunderbird

why? I read the guide but I don't understand.

linofex
  • 554
  • 1
  • 9
  • 28

4 Answers4

14

There are two issues here. First, when you run ps | grep ..., the grep process is also shown in the output of ps. The default ps output includes the arguments a process was launched with, not only the process's name. This means that if you run grep foo, and there is a running process called foo, there will be two ps results matching foo: the foo process and the grep itself since it is searching for foo. This is why you get two lines when running ps -f | grep thunderbird.

Now, the [ ] is a regular expression construct which defines a list of characters, a character class. For example, [abc] will match a or b or c. When you run ps -f | grep [t]hunderbird, that class only contains a single character so is equivalent to thunderbird without the brackets. However, the grep process was launched with [t]hunderbird as an argument this time, and not thunderbird. Therefore, its line in the output of ps will contain [t]hunderbird. It will look like this:

terdon   23101 10991  0 16:53 pts/3    00:00:00 grep --color [t]hunderbird

This means that it is not matched when you run ps -f | grep thunderbird since it contains [t]hunderbird and not thunderbird.

This is a common trick to avoid matching the grep process itself when running ps | grep. Another alternative is to run ps -f | grep foo | grep -v grep to exclude the grep. The best approach, however, is to use a program specifically designed for this, pgrep:

$ pgrep -l thunderbird
11330 thunderbird
terdon
  • 104,119
6

In the first case you're looking for any process with the word thunderbird in. There are two thunderbird and the grep command itself.

In the second you're also looking for t character followed by hunderbird, as the [t] means match any listed characters in the square bracket of which there's just the one, the letter t, but this time your two processes are

user  17410     1  0 10:09 ?        00:00:20 /usr/lib/thunderbird/thunderbird
user  18990 15896  0 12:25 pts/1    00:00:00 grep --color=auto [t]hunderbird

The second process does not match because the rexep [t]hunderbird does not match the literal string [t]hunderbird as the ] prevents the match.

3

Firstly, whether grep --color=auto thunderbird will appear on the process table and hence on the output of ps depends on the time i.e. how busy is your system & how much time it takes for ps to show something on it's output (by parsing the process table) that has started concurrently, grep in this case. Although this is a highly unlikely case and we can assume that that grep will appear on the output of ps.

Now, [] is a grep syntax which means (if not followed by other tokens) match any of the characters inside []. So when you use grep '[t]hunderbird', grep treats the [t] to match only t, as a result it would not appear in the output.

While using grep thunderbird, if it makes it way in the process table, we would find the grep process in the output as we are grep-ping for the same thing i.e. grep thunderbird.

Also note that grep is an alias to grep --color=auto causing it to appear in the output too.

heemayl
  • 93,925
1

The [] in grep is used for character matching. If we take grep [tb]all my_file.txt

It is equivalent to

grep tall my_file.txt
grep ball my_file.txt

It will execute grep with taking t+all and then it will execute grep by taking b+all.

For example: If we want to look for a word ABC or BBC in a file we can use the following grep command:

grep [AB]BC file_name 

Here the [] will make grep to expand the the word by taking A, then it will expand the word by using B, thus creating ABC and BBC.

Bidyut
  • 789
  • 7
  • 14