1

I have the following testfile.txt:

string1 1  
string2 2  
string3 3  
string1 2  
string2 4  
string3 6  
string1 3  
string2 6  
string3 9  

I have the following script:

#!bin/sh

oldstr="abc"  
while read line  
do  
    newstr=\`echo "$line" | sed 's/\(.*\)\( \)\([0-9].*\)/\1/'\`
    echo "$oldstr vs $newstr"

    if [ $oldstr == $newstr ] 
    then 
       echo "old $oldstr"
    else
       oldstr=$newstr
       echo "new $oldstr"
    fi
done < $@ | sort
echo "done"

I then run the script:

$ sh test.sh testfile.txt

and get the output:

abc vs string1  
new string1  
new string1  
new string1  
new string2  
new string2  
new string2  
new string3  
new string3  
new string3  
string1 vs string2  
string1 vs string2  
string1 vs string2  
string2 vs string3  
string2 vs string3  
string2 vs string3  
string3 vs string1  
string3 vs string1  
done

I'd like to know why, as I would expect the output to be:

abc vs string1  
new string1  
string1 vs string1
old string1  
string1 vs string1
old string1  
string1 vs string2
new string2  

and so on.

  1. Why isn't the "if" statement working?
  2. Why is the echo printing out of sequence?
  • I understand that the question is quite basic --- but I really do not understand the downvote without any comment. At least a link to RTFM should be given. – Rmano Jan 21 '14 at 2:59
5

1) they are out of order because you asked it: you prepare the whole list and then | sort them.

2) the test should be (standard sh syntax): if [ "$variable" = ... (not ==).

3) to test things, use sh -xv which will print every line before executing it and the result of expansions.

4) why do you escape the backticks?

5) You've got missing quotes around your variables

6) < $@ only works if there's only one argument to the script.

7) using read without -r and without removing the whitespace characters from $IFS probably doesn't make sense here.

8) you can't use echo with arbitrary data

9) It should be #!/bin/sh, not #!bin/sh

Working script:

#!/bin/sh 

oldstr="abc"  
while IFS= read -r line  
do  
    newstr=`printf '%s\n' "$line" | sed 's/\(.*\)\( \)\([0-9].*\)/\1/'`
    printf '%s\n' "$oldstr vs $newstr"

    if [ "$oldstr" = "$newstr" ] 
    then 
       echo "old $oldstr"
    else
       oldstr=$newstr
       printf '%s\n' "new $oldstr"
    fi
done < "$1" 

echo "done"

Moreover, you should change the input test file. The one you posted never triggers the "old" case.

If you want to sort the file before passing it to the loop, change the while line to:

sort -- "$@" | while IFS= read -r line 

and obviously remove the < $@ after done:

sort -- "$@" | while IFS= read -r line  
do  
   [...]
done
  • What I wanted to do was sort the file before passing it to the while loop. I realized what the code was actually doing was to pass the file to the while loop, which processed it and then piped it to the sort, not exactly what I want! How do I sort the file before passing it to the while loop? – EggHead Jan 21 '14 at 2:06
  • I strongly disagree on the it would be much better to use bash for scripting. – Stéphane Chazelas Jan 21 '14 at 7:48
  • @StephaneChazelas you are right that this is a personal preference --- I have removed it. Thanks for the edit --- useful corrections (I was lazy). – Rmano Jan 21 '14 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.