0

Not sure how to explain this but, what I am trying to achieve is this: - tailing a file and grepping for a patter A - then I want to pipe into another customGrepFunction where it matches pattern B, and if B matches echo something out. Need the customGrepFunction in order to do some other custom stuff.

The sticky part here is how to make the grepCustomFunction work here.In other words when only patternA matches echo the whole line and when both patterA & patternB match printout something custom: when I only run:

tail -f file.log | grep patternA

I can see the pattenA rows are being printed/tailed however when I add the customGrepFunction nothing happens.

tail -f file.log | grep patternA | customGrepFunction

And the customGrepFunction should be available globally in my bin folder:

customGrepFunction(){

 if grep patternB 
  then
     echo "True"
  fi


 }  

I have this setup however it doesn't do what I need it to do, it only echos True whenever I do Ctrl+C and exit the tailing. What am I missing here?

Thanks

Alim Hasanov
  • 197
  • 1
  • 3
  • 16
  • For guidance on how to write your function that reads text line-by-line, [BashFAQ #1](http://mywiki.wooledge.org/BashFAQ/001). For guidance on what can go wrong (to make it *look* like your code isn't working), see [BashFAQ #9](http://mywiki.wooledge.org/BashFAQ/009). – Charles Duffy Aug 24 '17 at 16:58

1 Answers1

3

What's Going Wrong

The code: if grep patternB; then echo "true"; fi

...waits for grep patternB to exit, which will happen only when the input from tail -f file.log | grep patternA hits EOF. Since tail -f waits for new content forever, there will never be an EOF, so your if statement will never complete.

How To Fix It

Don't use grep on the inside of your function. Instead, process content line-by-line and use bash's native regex support:

customGrepFunction() {
  while IFS= read -r line; do
    if [[ $line =~ patternB ]]; then
      echo "True"
    fi
  done
}

Next, make sure that grep isn't buffering content (if it were, then it would be written to your code only in big chunks, delaying until such a chunk is available). The means to do this varies by implementation, but with GNU grep, it would look like:

tail -f file.log | grep --line-buffered patternA | customGrepFunction
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Great that gets to what I want to do @Charles. – Alim Hasanov Aug 24 '17 at 17:13
  • Have a quick question though: in the $line~ patternB, how do I look for multiple patters, ? "B|B1|B2|" ? – Alim Hasanov Aug 24 '17 at 17:14
  • @AlimHasanov, but without the quotes -- quoting the right-hand side of `=~` makes it be treated as a literal string instead of an ERE. If you need to put a complicated regex in there, the best practice is to put it in a variable (and use that variable unquoted): `re='B|B1|B2'`, and then `[[ $line =~ $re ]]`. (And do note that the relevant regex syntax is ERE, not PCRE; you need to use `[[:space:]]`, not `\s`, for instance). – Charles Duffy Aug 24 '17 at 17:15
  • please find in a separate post, sorry, pressed wrong button – dimirsen Z Aug 24 '17 at 17:20