tags:

views:

162

answers:

4

Hi,

I have the following script

cat $1 | while read line
do
    line=`echo $line | tr "[:lower:]" "[:upper:]"`

    if [ "`echo $line | cut -f1 -d:`" = "foo" ] && \
       [ "`echo $line | cut -f2 -d:`" = "bar" ]; then
        echo 'exsist'
        exit 1;
    fi
done

everything works up to echo and then when the script hits exit it does not and keeps going. Any ideas.

Thanks

+3  A: 

You don't need that backslash - this is not the C shell.

The problem is that the while loop is in a sub-shell, which exits, but because it is run as a sub-shell, the main script continues.

In the context, the simplest fix is probably:

while read line
do
    line=`echo $line | tr "[:lower:]" "[:upper:]"`
    if [ "`echo $line | cut -f1 -d:`" = "foo" ] &&
       [ "`echo $line | cut -f2 -d:`" = "bar" ]; then
        echo 'exist'
        exit 1
    fi
done < $1

If you have to process multiple files ('cat "$@"' instead of 'cat $1'), then you have to work a lot harder bit harder:

cat "$@" |
while read line
do
    line=`echo $line | tr "[:lower:]" "[:upper:]"`
    if [ "`echo $line | cut -f1 -d:`" = "foo" ] &&
       [ "`echo $line | cut -f2 -d:`" = "bar" ]; then
        echo 'exist'
        exit 1
    fi
done
[ $? != 0 ] && exit 1

This checks the exit status of the pipeline consisting of 'cat' and 'while', which is the exit status of the 'while' loop, which will be 1 in the example if 'foo:bar' is found at the start of a line.

Of course, there are other ways to detect that, such as:

grep -s -q "^foo:bar:" "$@" && exit 1

This executes a lot less commands than the loop version. (If you need to allow for '^foo:bar$' as well, use egrep instead of plain grep.)

Jonathan Leffler
Not that much harder; while read line; do ...; done < <(cat "$@")
Charles Duffy
thanks a lot. it worked
@Charles, that's bashism.
ghostdog74
A: 

You can make your conditionals case-insensitive by adding shopt -s nocasematch above the test. To set things back to case-sensitive: shopt -u nocasematch.

Dennis Williamson
assuming the `bourne` tag really means the traditional bourne shell, As far as my memory goes, don't think there is a nocasematch option. correct me if i am wrong.
ghostdog74
As far as my memory goes, I've forgotten how to read!
Dennis Williamson
A: 

You're translating your text from lower case text to upper case text, but then testing against lower case, so you never get to the exit.

GreenMatt
+1  A: 

since you want to convert to upper case for every line, you can do it like this

#!/bin/sh

tr '[:lower:]' '[:upper:]' < file | while IFS=":" read -r a b c
do
    case "$a $b" in
        "FOO BAR" ) echo "exist";exit;;
        *) echo "$a $b";;
    esac
done

OR you can do it with just awk(nawk for Solaris)

nawk -F":" '
topper($1)=="FOO" && topper($2)=="BAR"{
    print "exist"
    exit
}
{
    print topper($0)
}
' file
ghostdog74