Grep with number - bash

How I can grep with number. I have following data
[240465] SERVICE ALERT: localhost;demo-jms2:Critical Services;CRITICAL;SOFT;2;Disk Space,OutConnectorResponse-MCASMS,OutConnectorResponse-SPONSORED-SMS,
[240465] SERVICE EVENT HANDLER: localhost;demo-jms2:Critical Services;CRITICAL;SOFT;1;notify-service-by-email
I want to grep this data with number '2' which is a parameter after 'SOFT'. Here my problem is i am getting both lines when I grep with 2 since 2 contains in the time stamp of second line..

There is already a bunch of answers recommending fixes to your grep expression. It can be the right thing to do if you work on a problem interactively, and a quick hack that narrows down the results right now is enough for you.
If you're writing a script, I would recommend something like this awk command:
awk -F';' '{if ($5==2) print}'
Or a more readable equivalent provided by #sudo_O in a comment:
awk -F';' '$5==2'
First we have to reconstruct a specification of what you want from your example. You're in the best position to do it reliably, but it looks like you want to find 2 in the fifth field of semicolon-separated fields. That's what the above command does.

Simply use the pattern ;2;
$ grep ';2;' file
[240465] SERVICE ALERT: localhost;demo-jms2:Critical Services;CRITICAL;SOFT;2;...
Or if you only want to match 2 following SOFT then use ;SOFT;2;
$ grep ';SOFT;2;' file
[240465] SERVICE ALERT: localhost;demo-jms2:Critical Services;CRITICAL;SOFT;2;...

Grep with more context:
grep "SOFT;2;" data
Mind the quotes, otherwise the ";" will be interpreted by the shell.

Try doing this :
grep 'SERVICE.*ALERT.*SOFT;2' file
I had added more patterns for unicity.

grep -Po "(?<=SOFT;)\d+"
with your data
kent$ echo "[240465] SERVICE ALERT: localhost;demo-jms2:Critical
Services;CRITICAL;SOFT;2;Disk Space,OutConnectorResponse-MCASMS,OutConnectorResponse-SPONSORED-SMS,
[240465] SERVICE EVENT HANDLER: localhost;demo-jms2:Critical Services;CRITICAL;SOFT;1;notify-service-by-email"|grep -Po "(?<=SOFT;)\d+"
2
1

Related

Search all occurences of a instance ids in the variable

I have a bash variable which has the following content:
SSH exit status 255 for i-12hfhf578568tn
i-12hdfghf578568tn is able to connect
i-13456tg is not able to connect
SSH exit status 255 for 1.2.3.4
I want to search the string starting with i- and then extract only that instance id. So, for the above input, I want to have output like below:
i-12hfhf578568tn
i-12hdfghf578568tn
i-13456tg
I am open to use grep, awk, sed.
I am trying to achieve my task by using following command but it gives me whole line:
grep -oE 'i-.*'<<<$variable
Any help?
You can just change your grep command to:
grep -oP 'i-[^\s]*' <<<$variable
Tested on your input:
$ cat test
SSH exit status 255 for i-12hfhf578568tn
i-12hdfghf578568tn is able to connect
i-13456tg is not able to connect
SSH exit status 255 for 1.2.3.4
$ var=`cat test`
$ grep -oP 'i-[^\s]*' <<<$var
i-12hfhf578568tn
i-12hdfghf578568tn
i-13456tg
grep is exactly what you need for this task, sed would be more suitable if you had to reformat the input and awk would be nice if you had either to reformat a string or make some computation of some fields in the rows, columns
Explanation:
-P is to use perl regex
i-[^\s]* is a regex that will match literally i- followed by 0 to N non space character, you could change the * by a + if you want to impose that there is at least 1 char after the - or you could use {min,max} syntax to impose a range.
Let me know if there is something unclear.
Bonus:
Following the comment of Sundeep, you can use one of the improved versions of the regex I have proposed (the first one does use PCRE and the second one posix regex):
grep -oP 'i-\S*' <<<$var
or
grep -o 'i-[^[:blank:]]*' <<<$var
You could use following too(I tested it with GNU awk):
echo "$var" | awk -v RS='[ |\n]' '/^i-/'
You can also use this code (Tested in unix)
echo $test | grep -o "i-[0-z]*"
Here,
-o # Prints only the matching part of the lines
i-[0-z]* # This regular expression, matches all the alphabetical and numerical characters following 'i-'.

How can extract word between special character and other words

I am trying to find a way, how to extract a word between special character and other words.
Example of the text:
description "CST 500M TEST/VPNGW/11040 X {} // test"
description "test2-VPNGW-110642 -VPNGW"
I am trying to achieve result like,only the word including VPNGW:
TEST/VPNGW/11040
test2-VPNGW-110642
I tried with grep and AWK, but looks like my knowledge is not so far enough.
The way to print with awk '{$1=""; $2=""; ... is not working due to the whole word is not always on the same position.
Thanks for the help!
With grep you can output only the part of the string that matches the regex:
grep -o '[^ "]\+VPNGW[^ "]\+' file.name
You could try something like:
grep -Eoi 'test.*[0-9]'
Of course this would be greedy and if there is another number after the ones in the required string it will grab up to there. Normally I would suggest an inverted test to stop at the thing you don't want:
grep -Eoi 'test[^ ]+'
The problem with this is like in your first example, there is more than one occurrence of the string 'test' and so the output for the first example is:
TEST/VPNGW/11040
test"
Of course knowing what your real data looks like you can make your own decision on what might best suit
Uou could go with the perl regex machine in grep and use a look-ahead:
grep -Eoi 'test[^ ]+(?= )'
Again though, if you have the string 'test' somewhere else on the line followed by a single space, this will still not work as desired.
Lastly, awk can do the job but you would need to cycle through each item or set RS to white space:
Option 1:
awk '{for(i=1;i<=NF;i++)if(tolower($i) ~ /test.*[0-9]/)print $i}'
Option 2:
awk 'tolower($i) ~ /test.*[0-9]/' RS="[[:space:]]+"
awk '/test2/{sub(/"/,"")}$0{print $4}/test2/{print $2}' file
TEST/VPNGW/11040
test2-VPNGW-110642

Need grep statement to exclude lines

I am running ufw in "open" mode just to collect stats to see if there are any attempts to access the server. UFW is running in "medium" logging so I can see all access to the server. When I check ufw.log, I need to run through the whole list manually.
I currently use:
grep 'IN=eth0' uwf.log
But this still leaves too many records for me to check manually
What I really need is:
Grep must only look for lines that contain IN=eth0 ( This part is
easy)
Grep must IGNORE lines with SRC=0.0.0.0 (These are dhcp broadcasts)
Grep must IGNORE lines with SRC=10.0.1.15 (10.0.X.X is my Nagios checking ftp service)
Can someone please help,
Thank you.
I would use awk:
awk '/IN=eth0/ && !/SRC=0\.0\.0\.0/ && !/SRC=10\.0\.1\.15/' uwf.log
Since awk supports boolean operations, multiple conditions can be expressed in a pretty simple way.
grep -v : This will make grep to exclude lines which matches the pattern.
grep -E : This will make grep to accept regular expressions (in this case multiple possibilities - which is separated by pipe).
grep "IN=eth0" uwf.log |grep -Ev 'SRC=0\.0\.0\.0|SRC=10\.0\.1\.15'
With GNU sed:
sed -rn '/IN=eth0/{/(SRC=0\.0\.0\.0|SRC=10\.0\.1\.15)/!p}' uwf.log

Does grep support the OR in a group?

I am looking at this question: https://leetcode.com/problems/valid-phone-numbers/
which asked using a cmd to extract the phone numbers.
I found this command works:
cat file.txt | grep -Eo '^(\([0-9]{3}\) ){1}[0-9]{3}-[0-9]{4}$|^([0-9]{3}-){2}[0-9]{4}$'
while this failed:
cat file.txt | grep -E '(^(\([0-9]{3}\))|^([0-9]{3}-))[0-9]{3}-[0-9]{4}'
I don't know why the second failed. Does it because grep doesn't support OR in a group?
No, it's because you dropped the space, so space in a phone number will no longer be allowed.
Also, the grouping in your regex seems to be off by a whack or two. What are you actually trying to express?
Finally, you have a useless use of cat -- grep can perfectly well read one or more input files without the help of cat.

To find exact name from the list in a bash file

I have following data file in bash. I want to search if the user entered webserver is present in the data file, if present it should return the Phase and Managed server name.
1 K1 tvtw1 tvtm1
1 K1 tvtw2 tvtw2
2 K2 tvtw26 tvtw26
3 k5 tvtw29 tvtm29
I tried grep "$webserver" serverList.lst | awk '{print $1}' but it returns multiple values for tvtw2. Is there any way to find exact server name from the list ?
If I understand correctly, if column 3 matches exactly, then you want to get the value of column 1:
awk -v serv=tvtw2 '$3 == serv {print $1}' serverList.lst
That is, we put the string you want to match in variable serv, and then use that as a filter expression in awk to match column 3 exactly.
you need add word boundary in your grep regex, so that tvtw26 won't be selected.
e.g. grep '\btvtw2\b' file ...
However since you have already used awk, you can consider to use awk for all. #janos 's answer showed how could it be done.
Try grep -w (-w stands for word regex)
However, grep | awk is useless-use-of-grep. See janos's answer for more optimal solution.

Resources