0
#!/bin/bash
  awk '{
           a[i++] = $1;
           a2[k++] = $NF;
          }
         END{
           for(j = 1; j<=NR; j++){
           printf"%d ",a[NR-j];
                 for(m = 2; m<NF;m++){
                   printf"%d ",$m;
                }
          printf"%d\n", a2[NR-j];
          }
        }'

I'm trying to flip the first and last column in any size matrix.Currently it is flipping the first and last column but prints the middle column values of the last row

4 Answers4

2

To flip the first and last column of each line (with different sizes), you could try something like :

[ ~]$ cat test.txt 
1 2 3 4 5
1 2 3
1 2 3 4 5 6
[ ~]$ awk '{tmp=$1; $1=$NF; $NF=tmp; print}' test.txt
5 2 3 4 1
3 2 1
6 2 3 4 5 1
Idriss Neumann
  • 3,760
  • 2
  • 23
  • 32
1

In AWK, fields can also occur on the left-hand side of an assignment:

seq 20 | paste -s -d ' ' -
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

seq 20 | paste -s -d ' ' - | awk '{ x=$1; $1=$NF; $NF=x; print }'
20 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 1
mavam
  • 12,242
  • 10
  • 53
  • 87
1

The END section of Awk is for processing after you've looped through your whole file. For example:

awk ' BEGIN { total = 0 }
      END   { print "The total of column 1 is " total}
      {
          total += $1
          print $0
      }'  file.txt

Here, I have a BEGIN and END clause. The BEGIN clause runs before my file is processed, and basically initializes the variable total to 0. (Not really necessary, but I wanted some sort of example).

The END clause runs after I've processed all of the lines in my file. It prints out the amount of total variable that I was calculating as I read in each line. My main part of my program (which is the last clause), simply adds column $1 to total and prints out the line.

What you want to do is change the way your line prints out as you read in that line. You want the last column (whatever that is) to print as your first column, and the first column to print as the last column. The NF variable tell you the number of fields you have:

awk '{
    for ( count = 1; count <= NF; count++ ) {
        if ( count == 1 ) {
            printf $NF "  "
        }
        else if ( count == NF ) {
            print $1
            continue
        }
        else {
            printf $count "  "
        }
    }
}' test.txt

Here, I have nothing but my main clause. I have a for loop that loops from the first to the last field of each line (Remember that each line is processed by my awk statement. If the count is 1, I'm on my first field, and I print the last field ($NF). If my count is equal to the number of fields on that line, I print the first field ($1). Otherwise, I print out the field itself.

This isn't the most compact form of awk that could be produced, but it's easy to understand.

Does it work?

Here's my test file:

one two three four five six
alpha beta gamma
bob carol ted alice
uno dos tres quatro cinco ses
alpha bravo charlie delta echo
apple banana carrot darren eggplant fennel

And here's the output:

six  two  three  four  five  one
gamma  beta  alpha
alice  carol  ted  bob
ses  dos  tres  quatro  cinco  uno
echo  bravo  charlie  delta  alpha
fennel  banana  carrot  darren  eggplant  apple
David W.
  • 105,218
  • 39
  • 216
  • 337
0

When a particular line is gone, awk no longer remembers its contents unless you store them explicitly. Hence, in the END block, $m means m-th value in the last line, and you didn't store m-th values of all the preceding lines anywhere.

Looks like you have to store the whole matrix in memory for this to work, or somehow do the job with two passes through the file instead of one.

Gassa
  • 8,546
  • 3
  • 29
  • 49