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

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.

Related

sed filtering of tshark dump: speedup

I'm filtering output generated by tshark with sed to only show Info and Bytes of packages. But when the tshark output gets too long, this can be too slow in some instances. I have not much experience with sed: Is there any way to speed this up? I think at the moment I run sed 5 times on each line with different expressions, but I remember researching this and find out that there is no "or" in my sed version. Would awk be faster?
tshark -P -x -r btdebug.snoop | sed -n 's/^.*\(Reassembled.*\)$/\1/p;s/^.*\(Sent.*\)$/\1/p;s/^.*\(Rcvd.*\)$/\1/p;s/^.*\(PT=.*\)$/\1/p;s/^[0-9a-f]*\s\(\(\s[0-9a-f][0-9a-f]\)\{1,16\}\).*$/\1/p'
EDIT: https://drive.google.com/open?id=1qzXkV9F9rjGmlvDo7CoxwjXZVRbQWDe- with example outputs from just tshark and after sed.

UNIX: error when I try to use array

I have this code and when I try it in FreeBSD it shows me a lot of errors... how can I fix it? I check directories, if it match with variable IGN. NAME_d should be an array.
max_d=$(find "${DIR}" -type d | wc -l)
for i in `seq 1 $max_d`
do
check_d=$(find "${DIR}" -type d | head -n "${i}" | tail -n -1 | tr '\/' '\n' | egrep -n "${IGN}")
if [ ! -z "$check_d" ]; then
NAME_d+=$i"d "
fi
done
directory_d=${NAME_d[*]}
sedCmds_d=${directory_d// /;}
Arrays are a bashism not supported by the Almquist shell, the default bourne style shell on FreeBSD (i.e. /bin/sh). An advantage of the shell is that most scripts run about 3 times faster.
If you want to use bashisms, use bash to execute your script. E.g. call it bash dirstat.sh or change the shebang.
This is the correct one for FreeBSD.
#!/usr/local/bin/bash
This is the portable version but requires PATH to be set:
#!/usr/bin/env bash
You also might have to install bash first: pkg add bash
Not sure if it will solve it, but if you're using bash, you should initiate NAME_d as an array
NAME_d=()
and then adding to the array you should also use parens, e.g.
NAME_d+=("${i}d ")

regular expression with grep not working?

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)'.

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

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!