0

I wrote some awk script to be executed while looping over {a..z}.txt files. I've been staring at this code for 30 minutes, but I just can't find what's wrong. The terminal complains that there is some syntax error around >, but I don't think that's where the bug is.

Basically, what I'm trying to do is this: Each line contains a string and a following set of numbers. I want to re-print the numbers so that the first number is the smallest one of them.

input: a 1125159 2554 290 47364290 47392510 48629708 68 60771

output:a 290 1125159 2554 47364290 47392510 48629708 68 60771

Could anyone help me find what is wrong with the below code?

for alphabet in {a..z} 
 do 
   awk -F$'\t' "NF>2{maxId=\$2;maxIndex=2;
             for(i=2; i<=NF; i++){
                if(maxId>\$i){maxId=\$i; maxIndex=i}
                }; 
             printf \"%s \t %s \t\",\$1, maxId; 
             for(i=2; i<=NF; i++){
                if(i!=maxIndex) 
                    printf \"%d \t\", \$i}; 
                    printf \"\n\";
                }" $alphabet.merged > $alphabet.out
    done 
pandagrammer
  • 841
  • 2
  • 12
  • 24
  • 1
    as you're not using any environment vars inside your awk script, why not just single quote the whole thing, i.e. `awk -F"\t" '{.....}' $alpha.merged > $alpha.out` ? And of course remove all the extra quoting on `"` and `$` chars. Good luck. – shellter Feb 26 '16 at 04:41
  • @shellter but I still need to escape the awk variables such as $1, $2...,right? – pandagrammer Feb 26 '16 at 04:43
  • 1
    no, you don't need to escape `i` or `$i` (depending on your need). Also, simplify debugging and just try `awk '...' a.merged > a.out` to work (comment out the loop, until you get the awk code working for a least 1 letter in the alpha). Good luck. – shellter Feb 26 '16 at 04:45
  • @shellter Thanks it worked!!!! – pandagrammer Feb 26 '16 at 04:56
  • 1
    @EdMorton Ed, I actually posted a similar question on stackoverflow, and followed the advice given. (http://stackoverflow.com/questions/34910638/looping-over-awk-commands-doesnt-work?noredirect=1#comment57557037_34910638) But I'll check out that book, thanks! – pandagrammer Feb 26 '16 at 20:23

1 Answers1

0

Here's how your script should really be written:

awk 'BEGIN { FS=OFS="\t" }
NF>2 {
    minIndex = 2
    for (i=3; i<=NF; i++) {
        if ( $minIndex > $i ) {
            minIndex = i
        }
    }

    printf "%s%s%s", $1, OFS, $minIndex
    for (i=2; i<=NF; i++) {
        if ( i != minIndex ) { 
            printf "%s%s", OFS, $i
        }
    }
    print ""
}' file
a       68      2554    290     47364290        47392510        48629708        1125159 60771

Don't shy away from white space and brackets as they help readability. I don't understand the purpose of the surrounding shell loop in your question though - I suspect all you really need is:

awk 'BEGIN { FS=OFS="\t" }
FNR==1 { close(out); out=FILENAME; sub(/merged/,"out",out) }
NF>2 {
    minIndex = 2
    for (i=3; i<=NF; i++) {
        if ( $minIndex > $i ) {
            minIndex = i
        }
    }

    printf "%s%s%s", $1, OFS, $minIndex > out
    for (i=2; i<=NF; i++) {
        if ( i != minIndex ) { 
            printf "%s%s", OFS, $i > out
        }
    }
    print "" > out
}' *.merged
Ed Morton
  • 188,023
  • 17
  • 78
  • 185