Objective: Always include the header line when using grep. In other words, do not perform pattern matching on the header, but only perform pattern matching on the body (from line 2 onwards).
Before looking at the solution, let’s take a closer look at the problem. Let’s try to grep processes with the name “ssh” in them.
1 2 3 |
$ ps aux | grep sshd root 2517 0.0 0.4 6464 1056 ? Ss 14:55 0:00 /usr/sbin/sshd root 2829 0.0 1.3 9892 3448 ? Ss 15:01 0:00 sshd: root@pts/0 |
As you can see from the above output, the processes that matched the name “ssh” are printed out, but the header row of the ps
command is missing. This is because it does not match the pattern “ssh”. The header output of the ps
command looks like this.
1 2 |
$ ps aux | head -1 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND |
Now, the problem is how can we include the above header in the grep output. So, our desired output has to be something like this – with the header on top.
1 2 3 |
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2517 0.0 0.4 6464 1056 ? Ss 14:55 0:00 /usr/sbin/sshd root 2829 0.0 1.3 9892 3448 ? Ss 15:01 0:00 sshd: root@pts/0 |
The way I normally accomplish it is by using the following syntax.
1 2 3 4 |
$ ps aux | ( IFS= read -r header; echo "$header"; grep ssh; ) USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2517 0.0 0.4 6464 1056 ? Ss 14:55 0:00 /usr/sbin/sshd root 2829 0.0 1.3 9892 3448 ? Ss 15:01 0:00 sshd: root@pts/0 |
The output of ps
is sent to a list of commands via command grouping. Within command grouping, the first line from the output of ps
is read by the read
command and the line is printed by the echo command. Subsequent output lines from ps
is fed to the grep command.
A better approach is to define the grouped commands in a shell function instead. Define the following grepb
function in your shell startup or profile file.
1 2 3 4 5 |
function grepb () { IFS= read -r header echo "$header" grep "$@" } |
To start using the grepb
function, either logout and login to the shell again or source the startup file. This will allow the current shell to recognise the function. Once done, use it with the following syntax.
1 2 3 4 |
$ ps aux | grepb ssh USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2517 0.0 0.4 6464 1056 ? Ss 14:55 0:00 /usr/sbin/sshd root 2829 0.0 1.3 9892 3448 ? Ss 15:01 0:00 sshd: root@pts/0 |