0

I need to grep multiple strings, but i don't know the exact number of strings. My code is :

s2=( $(echo $1 | awk -F"," '{ for (i=1; i<=NF ; i++) {print $i} }') )    
for pattern in "${s2[@]}"; do
    ssh -q host tail -f /some/path | 
      grep -w -i --line-buffered "$pattern" > some_file 2>/dev/null &
done

now, the code is not doing what it's supposed to do. For example if i run ./script s1,s2,s3,s4,.....

it prints all lines that contain s1,s2,s3....

The script is supposed to do something like grep "$s1" | grep "$s2" | grep "$s3" ....

3 Answers 3

1

grep doesn't have an option to match all of a set of patterns. So the best solution is to use another tool, such as awk (or your choice of scripting languages, but awk will work fine).

Note, however, that awk and grep have subtly different regular expression implementations. It's not clear from the question whether the target strings are literal strings or regular expression patterns, and if the latter, what the expectations are. However, since the argument comes delimited with commas, I'm assuming that the pieces are simple strings and should not be interpreted as patterns.

If you want the strings to be interpreted as patterns, you can change index to match in the following little program:

ssh -q host tail -f /some/path |
awk -v STRINGS="$1" -v IGNORECASE=1 \
    'BEGIN{split(STRINGS,strings,/,/)}
     {for(i in strings)if(!index($0,strings[i]))next}
     {print;fflush()}'

Note:

  1. IGNORECASE is only available in gnu awk; in (most) other implementations, it will do nothing. It seems that is what you want, based on the fact that you used -i in your grep invocation.

  2. fflush() is also an extension, although it works with both gawk and mawk. In Posix awk, fflush requires an argument; if you were using Posix awk, you'd be better off printing to stderr.

Sign up to request clarification or add additional context in comments.

6 Comments

i didnt use fflush. Im not sure i understand what it does, but im directing the ouput of tail to a file, and everything seems to work fine.
@user2864207: fflush() does the same thing as the grep option --line-buffered; that is, it forces every output line to be written immediately instead of being buffered.
i have a slight problem. the process does not run in the background. I need to kill tail before i can view the lines in the file
@user2864207 That's probably why you need the fflush().
@user2864207: Sorry, I don't understand what that has to do with anything. Neither awk nor tail produce any output to stderr; the only thing that might be written to stderr are connection errors from ssh.
|
0

You can use extended

egrep "$s1|$s2|$s3" fileName

If you don't know how many pattern you need to grep, but you have all of them in an array called s, you can use

egrep $(sed 's/ /|/g' <<< "${s[@]}") fileName

This creates a herestring with all elements of the array, replaces the field separator of bash (space) with | and if we feed that to we all strings that are in the array s.

3 Comments

i can't, because i don't know how many strings i am supposed to grep
i have entered the following line ssh -q host tail -f some/path | egrep -w -i --line-buffered "$(sed 's/ /|/g' <<< "${s2[@]}")" > file It gives me a snytax error
It's difficult to debug since I don't know what ssh -q host tail -f some/path outputs, but when I replace that with an echo command, it works for me. What's the exact error?
0

test.sh:

#!/bin/bash -x
a=" $@"
grep ${a// / -e } .bashrc

it works that way:

$ ./test.sh 1 2 3
+ a=' 1 2 3'
+ grep -e 1 -e 2 -e 3 .bashrc
(here is lots of text that fits all the arguments)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.