4

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
done

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"}'

4 Answers 4

11

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.

0
7

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

#!/bin/bash

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
2

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 ...
1
  • 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, 2017 at 15:04
0

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" '
    BEGIN{OFS=FS="\t"}
    NR==1{n=$i}
    {print $1,$i > n".txt"}' < "${Batch}.result.txt"
  i=$((i + 1))
done

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"

Your Answer

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