user2864207
user2864207

Reputation: 353

how to grep multiples variable in bash

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" ....

Upvotes: 0

Views: 896

Answers (3)

rici
rici

Reputation: 241931

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.

Upvotes: 1

Sergey Fedorov
Sergey Fedorov

Reputation: 2169

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)

Upvotes: 0

pfnuesel
pfnuesel

Reputation: 15350

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.

Upvotes: 0

Related Questions