2

I have this script where I ask for 4 patterns and then use those in a grep command. That is, I want to see if a line matches any of the patterns.

echo -n "Enter pattern1"
read pat1
echo -n "Enter pattern2"
read pat2
echo -n "Enter pattern3"
read pat3
echo -n "Enter pattern4"
read pat4

cat somefile.txt | grep $pat1 | grep $pat2 | grep $pat3 | grep $pat4 

The problem I'm running into is that if the user doesn't supply one of the patterns (which I want to allow) the grep command doesn't work.

So, is there a way to have grep ignore one of the patterns if it's returned empty?

10
  • @fedorqu -- I apologize for asking a duplicate question. If it's not painfully obvious by now, I'm very new to this. Commented Jun 22, 2016 at 13:04
  • @berserker do you want to filter with an AND or an OR? piping grep to another grep will filter the first results. Note that if you say pat=${pat:-""} will replace empty content with "" and then grep "$pat" it works, since grep "" file just returns the full content. Commented Jun 22, 2016 at 13:12
  • @fedorqu -- I want to filter by OR. Basically, I'm doing a syslog search and am taking input for src and dst ip as well as src and dst port. I want my search to run with either all 4 inputs or a mix of either of them. Commented Jun 22, 2016 at 13:20
  • berserker then, piping is wrong because it does AND. Check @Camusensei as a good start on how to do this. Commented Jun 22, 2016 at 13:22
  • @fedorqu -- You are correct. Sorry for all the confusion -- I'm learning and not articulating my intentions well. My previous comment is incorrect when I said OR. A usage example: I ask the user to provide 4 things (src ip/prt and dst ip/prt). They only give me src ip and dst ip and just skipping over src prt and dst prt. i would want to filter by AND. Does this make sense? Commented Jun 22, 2016 at 13:34

1 Answer 1

3

Your code has lots of problems:

  • Code duplication
  • Interactive asking for potentially unused information
  • using echo -n is not portable
  • useless use of cat

Here is what I wrote that is closer to what you should use instead:

i=1
printf %s "Enter pattern $i: "
read -r input
while [[ $input ]]; do
  pattern+=(-e "$input")
  let i++
  printf %s "Enter pattern $i (Enter or Ctrl+D to stop entering patterns): "
  read -r input
done
echo
grep "${pattern[@]}" somefile.txt

EDIT: This does not answer OP's question, this searches for multiple patterns with OR instead of AND...

Here is a working AND solution (it will stop prompting for patterns on the first empty one or after the 4th one):

pattern=
for i in {1..4}; do
  printf %s "Enter pattern $i: "
  read -r input
  [[ $input ]] || break
  pattern="${pattern:+"$pattern && "}/${input//\//\\/}/"
done
echo # skip a line
awk "$pattern" somefile.txt

Here are some links from which you can learn how to program in bash:

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

1 Comment

Note you can also use a C-syntax loop and say for ((i=1; i<=5; i++)); do ...; done, instead of using let (check How can I add numbers in a bash script also). +1 for the array trick. Note you can say input=${input:-""} for the case when no input is given.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.