3

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

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.

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
    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
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"
-2

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

  • 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