rlinux rlinux - 1 month ago 20
Bash Question

Use grep in array

Below is the script to find specific array of different words "bots,spyware,virus" in file, if file exists.

#!/bin/bash

#strings to find in file
NAME[0]="bots"
NAME[1]="spyware"
NAME[2]="virus"

#location of file
LOGS=/home/testing.txt

#define function to grep any of the above mentioned array strings in file
func(){
if `grep "${NAME[*]}" $LOGS`; then
echo "CRITICAL: ${NAME[*]}"
else
echo "errors not found"
exit
fi
}

#file exist or not exist
if [ -f $LOGS ]; then
echo " File Found"

#call functions
func
modified

else
echo "File Not Found"
exit


But
grep "${NAME[*]}" $LOGS
does not work. It shows below error:

grep: virus: No such file or directory
grep: bots: No such file or directory

Answer

Here is the solution for the problematic part.

Go to if-body when grep finds at least one entry of the array KEYWORDS in file FILE.
The following code works for array entries with special characters like space or *.

KEYWORDS[0]="virus"
KEYWORDS[1]="two words"
KEYWORDS[2]="special chars .+*?|()[]^&"

if grep -qF "${KEYWORDS[@]/#/-e}" -- "$FILE"; then
    # found a keyword
fi

What happens here?

  • grep -q
    Do not output anything. Exit on the first match. We don't have to scan the complete file if we already found a keyword.

  • grep -F
    Search fixed strings. Characters like *, |, or + lose their special meaning.

  • "{KEYWORDS[@]}"
    Each entry of the array expands to one quoted string. Here "virus" "two words" "special chars .+*?|()[]^&"

  • "${KEYWORDS[@]/#/-e}"
    Prepend -e to every entry of the array. Grep can search for multiple patterns using this option. grep -e"FirstPattern" -e"SecondPattern" ...

  • grep Pattern -- "$FILE"
    The -- is a hint, that "$FILE" should be interpreted as a file name. Its possible to name a file -eFunny, which would stop our script, because grep would think that no filename was provided and would wait for input from stdin. Its not really necessary here, but a good habit to establish. The so called double dash is available for most commands, not just grep.