1

I have a script that reads a file with a standard format where the 9th word is a number. I am trying to compare the number that is read from the file. I am able to read the line correctly and it works exactly as I want it to. But I get an error that says :

./age.sh: line 8: [: age: integer expression expected

Here is my script:

#!/bin/bash
if [ -f $1 ] ;
then
    while read -r LINE || [[ -n $LINE ]]; do
        name=$( echo $LINE | cut -d " " -f1 -f2)
        ago=$( echo $LINE | cut -d " " -f9)     
        echo "$name ----- $age"
        if [ $ago -gt 30 ] ; then
            echo "You get a discount"
        fi
    done < $1
    else
        echo "No file found"
fi

Here is a sample input file

#FirstName LastName SuperheroName Powers Weapons City Enemy isOutOfEarth Age
Bruce Wayne Batman Martial_arts No_Guns Gowtham Joker No 31
Clark Kent Superman Extreme_strength None Metropolitan Lex_Luther Yes 32
Oliver Queen Green_arrow Accuracy Bow_and_Arrow Star_city Cupid No 30
5
  • 1
    apparently $LINE's 9th field is not just an integer.
    – fedorqui
    Commented Jul 16, 2014 at 12:47
  • Does it print the error if only the 9th field is not a number? Or is it printing it in respect to the entire file?
    – gkmohit
    Commented Jul 16, 2014 at 12:49
  • 1
    Test it yourself: [ 't' -gt 1 ] && echo "yes" and [ 3 -gt 1 ] && echo "yes".
    – fedorqui
    Commented Jul 16, 2014 at 12:49
  • I was also wondering why this is needed: while read -r LINE || [[ -n $LINE ]]; do. I used it because most of the other examples used it.
    – gkmohit
    Commented Jul 16, 2014 at 14:40
  • You need || part because read fails on the last line without EOF, so you need to exit loop only if read fails and $LINE is empty.
    – gena2x
    Commented Jul 16, 2014 at 14:48

4 Answers 4

2

The specific error you are getting is because your script is also processing the header of your file. An easy fix would be to skip lines that begin with a #:

#!/bin/bash
if [ ! -f "$1" ]; then
   echo "No file found"
   exit 1
fi

## Use grep -v to print lines that don't match the pattern given. 
grep -v '^#' "$1" | 
while read -r LINE || [ -n "$LINE" ]; do
   name=$( echo "$LINE" | cut -d " " -f1,2)
   age=$( echo "$LINE" | cut -d " " -f9)
   echo "$name ----- $age"
   if [ "$age" -gt 30 ]; then
      echo "You got a discount"
   fi
done

However, since presumably you will also want to do stuff with your other columns, I would read all of them into variables directly:

#!/bin/bash
if [ ! -f "$1" ]; then
   echo "No file found"
   exit 1
fi

## read can take multiple values and splits the input line on whitespace
## automatically. Each field is assigned to one of the variables given.
## If there are more fields than variable names, the remaining fields
## are all assigned to the last variable.
grep -v '^#' "$1" | while read -r first last super powers weapons city enemy isout age; do
   echo "$first $last  ----- $age"
   if [ "$age" -gt 30 ]; then
      echo "You got a discount"
   fi
done
2
  • @terdon could you tell me what does while read -r LINE || [[ -n $LINE ]]; do do? Is the || here mean Or? and does [[ -n $LINE ]] mean if next line exists?
    – gkmohit
    Commented Jul 16, 2014 at 14:49
  • @Unknown yes, the || means OR. The [ -n ] test checks if a variable is null (see here), so that while loop will run as long as $LINE is set and not empty.
    – terdon
    Commented Jul 16, 2014 at 15:03
0
#!/bin/bash 
if [ ! -f "$1" ]; then
   echo "No file found"
   exit 1
fi

exec < $1

while read -r LINE || [ -n "$LINE" ]; do
   name=$( echo "$LINE" | cut -d " " -f1,2)
   age=$( echo "$LINE" | cut -d " " -f9)
   echo "$name ----- $age"
   if [ "$age" -gt 30 ]; then
      echo "You got a discount"
   fi
done
4
  • 1
    ARGH! I take it all back, my apologies. I was thinking about the [[ ]], not [ ]. I'll delete our previous comments since they are irrelevant and I was just being an idiot (I'm leaving this one so you don't think I'm deleting just so people can't see that I was being an idiot) :)
    – terdon
    Commented Jul 16, 2014 at 14:41
  • regarding quotes in echo line, what if name is not specified in the file and there is just space?
    – gena2x
    Commented Jul 16, 2014 at 14:41
  • 1
    Do come into the chat room posted above, we try to avoid long comment threads. As I said, you're quite right that quotes are needed in [ ] (but not [[ ]] :) nevertheless, this doesn't solve the OP's problem unless you also filter out the # signs. Anyway, my downvote was indeed mistaken and I have now removed it.
    – terdon
    Commented Jul 16, 2014 at 14:44
  • Yes, I bit overreacted too, author had no sample file than I posted my answer that's why there is no grep. Sorry, can't spend any time on this now - so can't chat. Removed my downvote too.
    – gena2x
    Commented Jul 16, 2014 at 14:46
0

So this is what I did:

#!/bin/bash

if [ -f $1 ] ; 
then 
    sum=0
    echo "#FirstName LastName City Age" 
    while read -r LINE || [[ -n $LINE ]]; do 
       name=$( echo $LINE | cut -d " " -f1 -f2) 
       city=$( echo $LINE | cut -d " " -f3) 
       age=$( echo $LINE | cut -d " " -f9) 
       check=$( echo $amount | grep -c "[0-9]") 
       if [ $check -gt 0 ]; then 
         if [ $age -gt 30 ] ; then 
            echo "You get a discount" 
         fi 
       fi 
    done < $1 

else 
    echo "No file found" 
fi 
3
  • You need || part because read fails on the last line without EOF, so you need to exit loop only if read fails and $LINE is empty.
    – gena2x
    Commented Jul 16, 2014 at 14:48
  • I removed the question you were asking here and converted it to a comment. While answering your own post is fine, please don't use answers to request more information.
    – terdon
    Commented Jul 16, 2014 at 14:49
  • @gena2x what about the -n ?
    – gkmohit
    Commented Jul 16, 2014 at 15:01
0

I'd read the line into a bash array:

if [[ -f $1 ]] ; then
    while read -ra line; do
        (( ${#line[@]} > 0 )) || continue  # skip empty lines
        name=${line[*]:0:2}
        age=${line[-1]}
        echo "$name ----- $age"
        if (( $age > 30 )); then
            echo "You get a discount"
        fi
    done < "$1"
else
    echo "No file found"
fi
#FirstName LastName ----- Age
Bruce Wayne ----- 31
You get a discount
Clark Kent ----- 32
You get a discount
Oliver Queen ----- 30

This is also not troubled by $age being a non-integer:

$ age=Age
$ [ $age -gt 30 ] && echo old || echo young
bash: [: Age: integer expression expected
young
$ (( $age > 30 )) && echo old || echo young
young
$ [[ $age -gt 30 ]] && echo old || echo young
young

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .