Extended regular expression grouping - grep

Trying to understand grouping in extended regular expressions. What is the difference between following two extended regular expressions.
$ echo "the CPU is" | grep -E '[Tt]he CPU|computer is'
the CPU is
$ echo "the CPU is" | grep -E '[Tt]he (CPU|computer) is'
the CPU is
On my Ubuntu bash shell the grep program in the former pattern highlights the CPU in red color. In the latter pattern grep highlights the CPU is. How is grouping change the pattern matching in the two cases above.

Because they are not equivalent! For example:
$ cat ip.txt
xyz The CPU 123
get the CPU and book
the computer is not here
The CPU is bad
$ grep -E '[Tt]he CPU|computer is' ip.txt
xyz The CPU 123
get the CPU and book
the computer is not here
The CPU is bad
$ grep -E '[Tt]he (CPU|computer) is' ip.txt
the computer is not here
The CPU is bad
[Tt]he CPU|computer is matches [Tt]he CPU OR computer is
[Tt]he (CPU|computer) is matches [Tt]he CPU is OR [Tt]he computer is
Similar to a(b+c)d = abd+acd in maths, you get a(b|c)d = abd|acd in regular expressions.

Related

regex start of line anchor alternative

I have "file.txt" with the following and I need to get only ip addresses that start a line.
I am using gnu utilities for windows and grep seems to be not behaving incorrectly.
Random Text Here
ABC 10.0.0.0 - 10.20.0.255
IP Ping Hostname
100.5.0.20 11ms N/S
GNU grep 2.5.4
grep -Po ^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} file.txt
10.0.0.0
10.20.0.255
100.5.0.20
Correct behavior should only allow 100.5.0.20 since i specified the start line anchor.
Any other Linux command solutions?
I ended up improvising,
grep -oP "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]{1,3} " file.txt| awk "{$1=$1};1" > file.txt
This will grab the ip addresses with 2 spaces, and then remove the spaces with awk.

How to output tcpdump with grep expression to stdout / file?

I am trying to output the following tcpdump grep expression to a file :
tcpdump -vvvs 1024 -l -A tcp port 80 | grep -E 'X-Forwarded-For:' --line-buffered | awk '{print $2}
I understand it is related to the line-buffered option, that sends the output to stdin. However, if I don't use --line-buffered I don't get any output at all from my tcpdump.
How can I use grep so that it will send my output directly to stdout / file in this case ?
I am trying to output the following tcpdump grep expression to a file
Then redirect the output of the last command in the pipeline to the file:
tcpdump -vvvs 1024 -l -A tcp port 80 | grep -E 'X-Forwarded-For:' --line-buffered | awk '{print $2}' >file
I understand it is related to the line-buffered option, that sends the output to stdin.
No, that's not with --line-buffered does:
$ man grep
...
--line-buffered
Force output to be line buffered. By default, output is line
buffered when standard output is a terminal and block buffered
otherwise.
so it doesn't change where the output goes, it just changes when the data is actually written to the output descriptor if it's not a terminal. It's not a terminal in this case - it's a pipe - so, by default, it's block buffered, so if grep writes 4 lines of output, and that's less than a full buffer block (buffer blocks, in this context, are typically 4K bytes in most modern UN*Xes and on Windows, so it's likely that those 4 lines won't fill the buffer), those lines will not immediately be written by grep to the pipe, so they won't show up immediately.
--line-buffered changes that behavior, so that each line is written to the pipe as it's generated, and awk sees it sooner.
You're using -l with tcpdump, which has the same effect, at least on UN*X:
$ man tcpdump
...
-l Make stdout line buffered. Useful if you want to see the data
while capturing it. E.g.,
tcpdump -l | tee dat
or
tcpdump -l > dat & tail -f dat
Note that on Windows,``line buffered'' means ``unbuffered'', so
that WinDump will write each character individually if -l is
specified.
-U is similar to -l in its behavior, but it will cause output to
be ``packet-buffered'', so that the output is written to stdout
at the end of each packet rather than at the end of each line;
this is buffered on all platforms, including Windows.
So the pipeline, as you've written it, will cause grep to see each line that tcpdump prints as soon as tcpdump prints it, and cause awk to see each of those lines that contains "X-Forwarded-For:" as soon as grep sees it and matches it.
However, if I don't use --line-buffered I don't get any output at all from my tcpdump.
You'll see it eventually, as long as grep produces a buffer's worth of output; however, that could take a very long time. --line-buffered causes grep to write out each line as it's produced, so it shows up as soon as grep produces it, rather than the buffer is full.
How can I use grep so that it will send my output directly to stdout / file in this case ?
grep is sending its (standard) output to awk, which is presumably what you want; you're extracting the second field from grep's output and printing only that.
So you don't want grep to send its (standard) output directly to the terminal or to a file, you want it to send its output to awk and have awk send its (standard) output there. If you want the output to be printed on your terminal, your command is doing the right thing; if you want it sent to a file, redirect the standard output of awk to that file.

Capturing certain value from iperf result using grep

I use iperf3 version and then I get the performance result like this in terminal :
[ 4] local 10.0.1.8 port 34355 connected to 10.0.1.1 port 5201
49,49,0,0,35500
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 2.19 MBytes 18.4 Mbits/sec 0 69.3 KBytes
CPU Utilization: local/sender 2.8% (0.7%u/3.3%s), remote/receiver 1.4% (0.6%u/0.9%s)
I want to use only certain values which I will use in the bash script later. What I want is like this :
35500,18.4,2.8
As far as I know I can use grep to print bandwidth only :
./src/iperf3 -c 10.0.1.1 -d -t 1 -V | grep -Po '[0-9.]*(?= Mbits/sec)'
but is it possible to obtain "35500,18.4,2.8" using grep and how to do it?
Thank you for the answers
grep with P(Perl-regex) option allows you to include multiple regexes,
$ grep -Po '(?<=,)[0-9]+$|[0-9.]*(?= Mbits/sec)|(?<=local\/sender )[^%]*' file | paste -d, - - -
35500,18.4,2.8
So your command would be,
$ ./src/iperf3 -c 10.0.1.1 -d -t 1 -V | grep -Po '(?<=,)[0-9]+$|[0-9.]*(?= Mbits/sec)|(?<=local\/sender )[^%]*' | paste -d, - - -

Convert check_load in Nagios to Zabbix

Hi I have just built my Zabbix server and in the process of configuring some checks currently setup in Nagios.
One these checks is check_load. Can anyone explain what this check means in Nagios and how I can replicate it in Zabbix.
In Nagios check_load monitors server load. Server load is a good indication of what your overall utilisation looks like : http://en.wikipedia.org/wiki/Load_(computing)
You can view server load easily on most *nix servers using the top command. The 3 numbers at the top right show your 1, 5 and 15 minute load averages. As a brief guide the load should be less than your number of processors. So for instance if you have a 4 cpu server then I would expect your load average to sit below 4.00.
I recently did a quick load monitor in nagios script format for http://www.dataloop.io
It was done quickly and needs a fair bit of work to work across other systems. But it gives a feel for how to scrape the output of top:
#!/bin/bash
onemin=$(top -b -n1 | sed -n '1p' | cut -d ' ' -f 13 | sed 's/%//')
fivemin=$(top -b -n1 | sed -n '1p' | cut -d ' ' -f 14 | sed 's/%//')
fifteenmin=$(top -b -n1 | sed -n '1p' | cut -d ' ' -f 15 | sed 's/%//')
int_fifteenmin=$( printf "%.0f" $fifteenmin )
echo "OK | 1min=$onemin;;;; 5min=$fivemin;;;; 15min=$fifteenmin;;;;"
alert=10
if [ "$int_fifteenmin" -gt "$alert" ]
then
exit 2
fi
exit 0
Hope this explains enough for you to create a Zabbix equivalent.
In zabbix, it is a zabbix agent built-in check. Search for system.cpu.load here.
As for what it measures, the already posted link to wikipedia article is a great read.

combine grep with the watch and netstat command

Red Hat Enterprise Linux Server release 5.4 (Tikanga)
2.6.18-164.el5
I am trying to use the watch command combined with the netstat to see the 2 programs using certain ports.
However, with the command I using below doesn't work for both words:
watch -n1 "netstat -upnlt | grep gateway\|MultiMedia"
Is this the correct way to grep for both program names.
If I use one its ok, but both together doesn't work.
For the grep you need:
"grep gateway\|MultiMedia"
So perhaps try:
watch -n1 'netstat -upnlt | grep "gateway\|MultiMedia"'
There's also the new way of doing things... grep -E is nice and portable (Or egrep, which is simply quick for grep -E on linux&bsd) so you don't have to escape the quote. From the man pages:
-E Interpret pattern as an extended regular expression (i.e. force
grep to behave as egrep).
So...
watch "netstat -upnlt | grep -E 'gateway|multimedia'"
or
watch "netstat -upnlt | egrep 'gateway|multimedia'"
I had a similar problem monitoring an ssh connection.
> netstat -tulpan|grep ssh
tcp 0 0 192.168.2.52:58072 192.168.2.1:22 ESTABLISHED 31447/ssh
However watch -n 1 'netstat -tulpan|grep ssh' shows no output (apart from message from watch).
If I change it to watch -n 1 'netstat -tulpan|grep ":22"' I get the required output line. It seems as if the -p option is ignored when netstat is run through watch. Strange.

Resources