Teju Priya
Teju Priya

Reputation: 665

Conditional loop issue in shell

I have a shell script with if and elif logic. I am trying to check keyword match with grep command.Whatever keywords I am passing the script is executing last block only.here is my script.

tail -n 0 -F hive-server2.log | \
while read LINE
do
if [ `echo "$LINE" | grep -c "select .*" ` -gt 0 ]
then
  AuditTypeID=15
  QueryResult=$(grep -oEi 'SELECT .*' hive-server2.log | sed -n \$p)
elif [ `echo "$LINE" | grep -c "CREATE" ` -gt 0 ]
then
  AuditTypeID=13
  QueryResult="$(grep -oEi 'CREATE EXTERNAL TABLE [a-zA-Z][a-zA-Z0-9_]*' hive-server2.log | sed -n \$p)"
fi
done

If I pass "select * from table", It is executing elif part only. Even If I pass any query It is executing elif part. Any help would be appreciated.

Upvotes: 0

Views: 114

Answers (2)

kyodev
kyodev

Reputation: 583

with my simulation, that works with:

tail -n 0 -F hive-server2.log | \
while read line; do
    if [[ "$line" =~ select[[:blank:]]count ]]; then
        echo "action select count"
    elif [[ "$line" =~ select[[:blank:]]\*[[:blank:]]from ]]; then
        echo "action select * from"
    elif [[ "$line" =~ DROP ]]; then
        echo "action drop"
    elif [[ "$line" =~ CREATE ]]; then
        echo "action create"
    fi
done
  • as said tripleee:
    • tail -n 0 -f starts reading the file without seeking back
    • tail -n 1 -f seeks back and prints the last line
  • if you test with an echo, ensure to quote, example:
    echo "select * from table" >> hive-server2.log

Upvotes: 0

tripleee
tripleee

Reputation: 189387

Your logic looks very much like you need to discover the case statement.

tail -n 0 -F hive-server2.log |  # No backslash necessary here
tr A-Z a-z |  # Convert to lower case
while read -r line    # -r option; lowercase variable
do
    case $line in
      *'select '*)
          AuditTypeID=15
          QueryResult="$(grep -oEi 'SELECT .*' hive-server2.log | sed -n \$p)";;
       *create*)
          AuditTypeID=13
          QueryResult="$(grep -oEi 'CREATE EXTERNAL TABLE [a-zA-Z][a-zA-Z0-9_]*' hive-server2.log | sed -n \$p)";;
done

The antipattern if [ $(echo "blah" | grep -c something) -gt 0 ] is common but very unidiomatic (see useless use of grep); the way to check if grep matched something is just if echo "blah" | grep -q something but here, you can obviously use the shell's built-in pattern-matching facilities to simplify even further.

Uppercase variable names are reserved for system use; I recommend lower or mixed case for all your script's private variables.

Your code might still have other bugs (rereading the entire file to find the latest create or select statement very much looks like something you should probably refactor) but the immediate problem seems to be that you are matching a lowercase string against an uppercase pattern. The code above folds the input to lower case, which is an easy fix as such, but not always a desirable workaround (perhaps you want to see the original line, not the case-folded version, in the output?). Bash 4.x provides a simple facility for case-folding so you could say case ${line,,} and remove the tr.

Upvotes: 1

Related Questions