regular expression with grep not working? - regex

I am running cygwin, grep 2.21 on Windows 7.
I am trying to get all tcp connections from netstat, so I run the following:
netstat | grep -i "^(TCP|UDP)"
Now, it returns nothing, but when I run netstat it clearly returns a bunch of tcp connections. I also tried :
netstat | egrep -i "^(TCP|UDP)"
Also returns nothing. What am I missing here? I thought that the caret means "begins with". Thanks.

For me, netstat | grep -P '(tcp|udp)' worked.
You may want to use the i flag to ignore the case if necessary.
netstat | grep -Pi '(TcP|UDp)'
About the other answer here, using egrep or grep -e gives the same result. Based on this.
The -P flag was inspired by this post.
Using the option -P, accordingly to man grep, sets the pattern interpreter as perl. Not sure why it did not work without -P though.

netstat outputs the protocol using lower case characters. Try either of the following:
netstat | grep '^\(udp\|tcp\)'
or
netstat | egrep '^(udp|tcp)'
The difference between the two is that egrep supports an extended regular expression syntax in which (, ) and | should not be escaped. As Reuel Ramos Ribeiro noted,
egrep is equivalent to using grep -e so alternatively one could use netstat | grep -e '^(udp|tcp)'.

Related

The following code is showing error in AIX server but working fine in Red Hat server

string='binddn:cn=SxX.UXxxxM-E2A,OU=CA,OU=AI INFRASTRUCTURE,DC=i,DC=companyname,DC=com'
The working peice of code in Red Hat
dn=($(grep -oi 'cn=[^():]*dc=com' <<< "$string"))
I modified the code for AIX and modified code is
dn=($(grep -xi 'cn=[^():]*dc=com' "$string"))
The code is working perfect in RedHat server, the output in redhat is
dn[0]="cn=SxX.UXxxxM-E2A,OU=CA,OU=AI INFRASTRUCTURE,DC=i,DC=companyname,DC=com"
The error in AIX is
grep: can't open binddn:cn=SxX.UXxxxM-E2A,OU=CA,OU=AI INFRASTRUCTURE,DC=i,DC=companyname,DC=com
Edited:
Another example:
string = "userbasedn:DC=i,DC=companyname,DC=com?subtree?(&(objectcategory=person)(uidNumber=*)(|(memberOf:1.2.840.113556.1.4.1941:=cn=example1,OU=GROUPS,OU=AI INFRASTRUCTURE,DC=i,DC=companyname,DC=com)(memberOf:1.2.840.11.1.4.1941:=cn=example2,OU=GROUPS,OU=AI INFRASTRUCTURE,DC=i,DC=companyname,DC=com)))
groupbasedn:DC=i,DC=companyname,DC=com?subtree?(&(objectcategory=group)(gidNumber=*))"
expected output
dn[0]=cn=example1,OU=GROUPS,OU=AI INFRASTRUCTURE,DC=i,DC=companyname,DC=com
dn[1]=cn=example2,OU=GROUPS,OU=AI INFRASTRUCTURE,DC=i,DC=companyname,DC=com
If you can use awk, try this:
echo "$string" | awk -F"cn=" 'NF>1{$0=tolower($0);for (i=2;i<=NF;i++) {split($i,a,"dc=com)");print FS a[1]"dc=com"}}'
cn=example1,ou=groups,ou=ai infrastructure,dc=i,dc=companyname,dc=com
cn=example2,ou=groups,ou=ai infrastructure,dc=i,dc=companyname,dc=com
The second argument to grep is a file name, not a string. AIX correctly reports that it cannot find a file with that name. You would get the same error on Red Hat if you tried the same command.
Unfortunately, the -x option doesn't do what you hope; it checks whether the entire line of input matches the regex. Again, you will find exactly the same behavior on Red Hat.
According to the AIX grep manual page it supports the -o option just fine, though.
The Bash "here string" syntax <<<"string" is not available if you don't have Bash, but it is easy to rephrase portably:
printf '%s\n' "$string" |
grep -oi 'cn=[^():]*dc=com'
If you don't have grep -o, try with sed:
printf '%s\n' "$string" |
sed -n 's/.*\(cn=[^():]*dc=com\).*/\1/p'
This is not exactly the same, because the first .* is greedy. If you expect more than one match on a line, you will need a slightly more complex regex.

Piping of grep is not working with tail? [duplicate]

This question already has answers here:
How to 'grep' a continuous stream?
(13 answers)
Closed 8 years ago.
I am trying to debug one scenario by checking the logs, here is my command
tail -f eclipse.log | grep 'enimation' | grep -i 'tap'
Basically what I am trying to to is that, of all of the line, I am printing lines with enimation in it, then of all of the animation, I want to see the animation with "tap" in it.
Here is the sammple data for which it is returning empty results
*******enimation error*********TapExpand
*******enimation error*********TapShrink
This is returning empty results.
While if I run this command
tail -f eclipse.log | grep -i 'enimation.*tap'
it returns correct results. Can someone please explain to me, what is the difference between the above two command and why there is a discrepancy in the results. They both seem identical to me.
grep is buffering it's output. To tell GNU grep to spit out output line-by-line you need to use --line-buffered option in grep to make it work:
tail -f eclipse.log | grep --line-buffered 'enimation' | grep --line-buffered -i 'tap'
As per 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.
The output of the grep in the middle is not a terminal, so it is using block buffering instead of line buffering. You have to force line buffering using --line-buffered option.
tail -f eclipse.log | grep --line-buffered 'enimation' | grep -i 'tap'
In case of other commands, which don't provide such an option, you can use stdbuf command to force line buffering, e.g.:
tail -f eclipse.log | stdbuf -o1 grep 'enimation' | grep -i 'tap'
Your output is getting buffered. Try:
tail -f eclipse.log | grep --line-buffered 'enimation' | grep --line-buffered -i 'tap'
Try adding the -E option to grep. A lot of reflex features don't work without it. I usually refer to it as the "yes, I do know what I'm doing" option.

Making a mistake with | (or) in regular expressions

I'm sure I'm doing something really obviously wrong here, but I can't figure out what. Using grep from a bash shell, I have a file test.txt:
ABC123
ABC456
ABC789
DEF123
DEF456
DEF789
Now at the command line:
$ grep ABC test2.txt
ABC123
ABC456
ABC789
$ grep DEF test2.txt
DEF123
DEF456
DEF789
So those work great. Now, I expect the following command to print the whole file, but:
$ grep ABC\|DEF test2.txt
$ grep (ABC)\|(DEF) test2.txt
-bash: syntax error near unexpected token `ABC'
$ grep \(ABC\)\|\(DEF\) test2.txt
$ grep 'ABC|DEF' test2.txt
What am I doing wrong?
Turn on the extended regex with -E:
grep -E "ABC|DEF" test2.txt
As others have pointed out, standard grep command does not support the or syntax. Unfortunately, from there, things are a mishmash.
Some systems have a egrep that does offer or syntax.
Some systems can use a -E or -P (for Perl) flag to extend grep syntax.
Some systems have both the -E and egrep that do the same thing. This implies that there are systems out there where grep -E and egrep are not the same. (sad but true).
Some systems now use the extended regular expressions in their standard grep command. Apparently, your system doesn't.
Read your manpages to see what your system does support. Some systems have a manpage for re_formatthat will explain what they support and don't support in extended format.
Then again, you could always just use a Perl one-liner:
$ perl -ne "print if /(ABC)|(DEF)/" test.txt
At least you know all the stuff that supports.
I don't think standard syntax supports it. You could use -P switch if available:
grep -P "(ABC|DEF)" test2.txt
Use egrep instead, which is the same as using grep -E:
egrep 'ABC|DEF' test2.txt

grep with regexp: whitespace doesn't match unless I add an assertion

GNU grep 2.5.4 on bash 4.1.5(1) on Ubuntu 10.04
This matches
$ echo "this is a line" | grep 'a[[:space:]]\+line'
this is a line
But this doesn't
$ echo "this is a line" | grep 'a\s\+line'
But this matches too
$ echo "this is a line" | grep 'a\s\+\bline'
this is a line
I don't understand why #2 does not match (whereas # 1 does) and #3 also shows a match. Whats the difference here?
Take a look at your grep manpage. Perl added a lot of regular expression extensions that weren't in the original specification. However, because they proved so useful, many programs adopted them.
Unfortunately, grep is sometimes stuck in the past because you want to make sure your grep command remains compatible with older versions of grep.
Some systems have egrep with some extensions. Others allow you to use grep -E to get them. Still others have a grep -P that allows you to use Perl extensions. I believe Linux systems' grep command can use the -P extension which is not available in most Unix systems unless someone has replaced the grep with the GNU version. Newer versions of Mac OS X also support the -P switch, but not older versions.
grep doesn't support the complete set of regular expressions, so try using -P to enable perl regular expressions. You don't need to escape the + i.e.
echo "this is a line" | grep -P 'a\s+line'

Why does this `grep -o` fail, and how should I work around it?

Given the input
echo abc123def | grep -o '[0-9]*'
On one computer (with GNU grep 2.5.4), this returns 123, and on another (with GNU grep 2.5.1) it returns the empty string. Is there some explanation for why grep 2.5.1 fails here, or is it just a bug? I'm using grep -o in this way in a bash script that I'd like to be able to run on different computers (which may have different versions of grep). Is there a "right way" to get consistent behavior?
Yes, 2.5.1's -o handling was buggy:
http://www.mail-archive.com/bug-grep#gnu.org/msg00993.html
Grep is probably not the right tool for this; sed or tr or even perl might be better depending on what the actual task is.
you can use the shell. its faster
$ str=abc123def
$ echo ${str//[a-z]/}
123
I had the same issue and found that egrep was installed on that machine. A quick solution was using
echo abc123def | egrep -o '[0-9]*'
This will give similar results:
echo abc123def | sed -n 's/[^0-9]*\([0-9]\+\).*/\1/p'
Your question is a near-duplicate of this one.
Because you are using a regex so you must use either:
grep -E
egrep (like Sebastian posted).
Good luck!