0

I want to create a for loop that runs from 1 to a number stored in a variable. But it produces this error:

Syntax error: Bad for loop variable

This is my script:

#!/bin/bash

count_lines () 
{
  local f=$1  
  l=`wc -l $f | sed 's/^\([0-9]*\).*$/\1/'`
}
echo "$0 counts the lines of code" 
l=0
while [ "$*" != ""  ]
do
        count_lines $1
        echo "$1: $l"
        shift
done
for(( i= 0 ; i <= ${l} ; i++))
do
   title=$(grep -oPm1 "(?<=<title>)[^<]+" <<< "$0")
   echo "$title"
done
  • Small trick: wc -l <filename (note the left-angle) outputs just the count and you don't need to fiddle with sed or even something cheaper like ${var% *}. That said, if you really want to look for XML construct(s?) in the file(s?) they are unlikely to be related to the number of lines; one of the main features of XML is that it is stream-oriented, not line-oriented. – dave_thompson_085 Dec 6 '15 at 2:20
  • for (( i= 0 ; i <= ${l} ; i++)) space missing here. And in (( )) use i <= l -- ${} is unnecessary and a missing l actually messes up with the syntax. – Arthur2e5 Dec 9 '15 at 3:18
1

Make sure that the script is executable, and run the script by just typing the command, including its path. For example, if the script is called foo and is in the current directory, run

./foo

Given the error message, you are doing something like sh foo. This runs the script under sh, not bash. sh on your machine is a different shell, probably dash, which doesn't support the for loop syntax you used. By running ./foo, your script will be executed by the shell mentioned in the first line, which is bash.

Your script is weird in several places:

  • Always put double quotes around variable substitutions: "$1", "$f", etc.
  • That while [ "$*" != "" ] … loop is a very roundabout way of iterating over the arguments of the script. The simple, idiomatic way is

    for x; do
      count_lines "$x"
    done
    

    or

    for x in "$@"; do
      count_lines "$x"
    done
    
  • I'm not sure what you're trying to do with title=$(grep -oPm1 "(?<=<title>)[^<]+" <<< "$0"); "$0" is the path to the script, so you're searching the regexp (?<=<title>)[^<]+ in the path to the script, which doesn't make much sense.
  • I'm trying to extract a value from an xml document that has been read into my script as a variable with title=$(grep -oPm1 "(?<=<title>)[^<]+" <<< "$0") – engineer Dec 5 '15 at 23:21
  • and I wish to extract the all values between titles with a loop – engineer Dec 5 '15 at 23:22
  • @engineer Fix the parts you understand, then post a new question with your updated script, some sample input, and the desired output. – Gilles Dec 5 '15 at 23:30
  • I test my machine's shell with ps -p $$ and it is bash @Gilles – engineer Dec 5 '15 at 23:30
  • @engineer That shows you which shell you're running interactively. But given the error message you got, you are not running the script with bash. Once again, run /path/to/script instead of sh /path/to/script or whatever it is you're doing. – Gilles Dec 5 '15 at 23:33
0

The main problem I believe is with not testing if the file actually exists and getting a count l that is invalid for the for loop.

Take a look at this (very modified) similar script to give you some ideas:

#!/bin/bash

count_lines() {
if [[ -r $1 ]]; then     # if the file exist.
  l="$(wc -l "$1")"      # count the number of lines.
  l="${l%%[^0-9]*}"      # remove anything that is not a digit from the end.
else
  l=0
fi
}
echo "$0 counts the lines of code"

for file; do               # while there is an argument.
  count_lines "$file"    # execute the function above
  echo "$file: $l"       # print the number of lines.
done

echo "$(grep -oPm1 "(?<=<title>)[^<]+" "$0")"

I can not understand why you try to run l times a command (grep) to find title inside a file. One time is enough.

Also, the grep command is reading the script (not an external file).

As Gilles said: heavily correct your code, post a new question.

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.