Error in excuting while loop

can you please support me to understand what is wrong in this code, I am getting error as

sytnax error near unexpected token if
 if [ -n $word ] then

code is

cat text.txt | /path/mapper.sh 

data in file is

hi hi how how are you
while read line
do
 for word in $line do
 if [ -n $word ] then
	wcount=`echo $word | wc -m`;
	wlength=`expr $wcount - 1`;
	letter=`echo $word | head -c1`;
	echo -e "$lettert$wlength";
 fi
done
done

Hi,

 for word in $line do
 if [ -n $word ] then

should be

 for word in $line
 do
   if [ -n $word ]
   then

a newline may also be replace by a semicolon

1 Like

Further quote $word, at least in

 if [ -n "$word" ]; then

This is because the shell evaluates it first then passes it to the [ ] test that will not see an empty string and might give a syntax error.
BTW most shells understand

 if [[ -n $word ]]; then

where parsing and syntax check happens before $word is evaluated.

1 Like

You have already been explained what led to the error you got. This is a side issue:

wcount=`echo $word | wc -m`

You should NOT use backticks for this kind of operation. If you want to run a series of commands and feed the output of these into a variable do it with modern POSIX means instead of outdated (and in the meanwhile deprecated) backticks:

wcount=$(echo $word | wc -m)

This will do the same but - in sharp contrast to backticks - can even be nested:

var=$(command1 $(command2 | command3) | command4)

Another thing is this:

letter=`echo $word | head -c1`

Use parameter substitution for this, which is way faster and uses far less system resources:

letter="${word%${word#?}}"

I hope this helps.

bakunin

1 Like

No variable $lettert

I would like to suggest the following snip:

while IFS= read line; do
  for word in $line; do
      if [ -n $word ]; then
          echo "${word}: ${#word}"
      fi
  done
done < "$@"

After making the script executable it can be invoked as:

/path/to/mapper.sh /path/to/text.txt

This other one could be an evolution of it:

while IFS=  read line; do
    for word in $line; do
        [ -n $word ] && echo "${word}: ${#word}"
    done
done < "$@"

It doesn't hurt but it doesn't matter to double quote the variable word (in this case). There is no need to protect against variable word splitting because of the for loop

In fact, this could be one of those occasions where the following design might be acceptable.

for word in $(cat text.txt); do
   [ -n $word ] && echo "$word ${#word}"
done

Please, do not use a for loop to read from a $(cat file) to just read from a file. Normally, you want to prevent exactly what you want this time.

1 Like