I have an awk command which runs well on terminal: this awk command creates different file according to their column header. awk command:

for((i=2;i<5;i++)); do 
    awk -v i=$i 'BEGIN{OFS=FS="\t"}NR==1{n=$i}{print $1,$i > n".txt"}' ${Batch}.result.txt

the same command when incorporated in a shell script shows error:

Syntax error: Bad for loop variable

It worked the following way. I tried with she-bang as suggested but it repeated the error.

for i in 2 3 4; do awk -v i=$i 'BEGIN{OFS=FS="\t"}NR==1{n=$i}{print $1,$i  n".txt"}'

I don't think the error has anything to with your Awk command. I think you are running it in the POSIX bourne shell sh in which for-loop construct with (( is not supported.

Run the script with shebang set to the path where bash is installed. Usually it is safe to do #!/usr/bin/env bash because #!/usr/bin/env searches PATH for bash, and bash is not always in /bin, particularly on non-Linux systems. For on a OpenBSD system, it's in /usr/local/bin.

| improve this answer | |

It is likely that the script is being interpreted by /bin/sh rather than by bash (or ksh93 or any other shell that understands the C-like for-loop).

Make sure that the script has a #!-line saying


at the very top of the file (change to the shell and path that you want to be using), or that you run the script using the correct interpreter explicitly, for example:

bash ./scriptname
| improve this answer | |

A three-parameter loop control expression in bash should be specified as:

for (( EXP1; EXP2; EXP3 ))

But in your simple case I would just use:

for i in {2..4}; do ...
| improve this answer | |
  • 1
    Isn't the first syntax the same as in the question? If he's using a shell that doesn't understand that, it won't understand {2..4} either. He needs to specify the shell properly, as in the other answers. – Barmar Nov 3 '17 at 15:04

For completeness, the POSIX equivalent of your ksh93-syntax command (so would work with any modern implementation of sh including your ash-based shell like dash or busybox ash) would be:

i=2; while [ "$i" -lt 5 ]; do
  awk -v i="$i" '
    {print $1,$i > n".txt"}' < "${Batch}.result.txt"
  i=$((i + 1))

Though here, it would make more sense to write it:

awk -F '\t' -v OFS='\t' '
  NR == 1 {for (i = 2; i < 5; i++) file[i] = $i".txt"}
  {for (i = 2; i < 5; i++) print $1,$i > file[i]}' < "${Batch}.result.txt"
| improve this answer | |

It seems that the bash is tryng to expant the $i variable in the i=$i statement (that is interpreted as i= ). Try to escape the $i with slashes \$i

| improve this answer | |
  • 1
    There's nothing wrong with this apart from $i not being double quoted. This (-v i="$i") is the correct way of passing the values of shell variables into awk. – Kusalananda Nov 3 '17 at 13:34
  • 1
    The variable needs to be expanded. And @Kusalananda There's no need to quote a variable that you know is just a number. – Barmar Nov 3 '17 at 15:05
  • 2
    It seems a good habit to quote variable expansions; see the semi-contrived example: unix.stackexchange.com/a/280935/117549 – Jeff Schaller Nov 4 '17 at 3:52

Your Answer

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