0

I have few files as:

ifile1.txt       ifile2.txt       ifile3.txt
3  5  2  2       1  2  1  3       4  3  4  1 
1  4  2  1       1  3  0  2       5  3  1  5 
4  6  5  2       2  5  5  1       3  4  3  1 
5  5  7  1       0  0  1  1       4  3  4  0 
2  3  2  4       3  2  4  1       3  1  2  1

I need to copy 4th row from each file and paste as columns in ofile.txt as:

ofile.txt
5    0   4
5    0   3
7    1   4
1    1   0

I was able to do it in the following way, but looking for a direct/short method.

I first converted the rows of each file into columns using awk

awk '{ 
for (i=1; i<=NF; i++)  {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {    
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
    str=str" "a[i,j];
}
print str
}
}' ifile1.txt > ofile1.txt

Then I used used paste command as

paste ofile* > ofile.txt

Finally used awk again to print the required columns.

Kay
  • 1,957
  • 2
  • 24
  • 46

3 Answers3

4

As Deepu mentions in his good answer, saying FNR==4 suffices to print the fourth line on every file:

awk 'FNR==4' files*

With this you get something like

5  5  7  1
0  0  1  1
4  3  4  0

And now you just need to transpose the array. For this I created a little script some time ago, that I named transpose (very good at names, I know):

transpose () {
awk '{for (i=1; i<=NF; i++) a[i,NR]=$i; max=(max<NF?NF:max)}
        END {for (i=1; i<=max; i++)
            {for (j=1; j<=NR; j++) 
                printf "%s%s", a[i,j], (j<NR?OFS:ORS)
            }
        }'
}

All together, you just need to say:

$ awk 'FNR==4' f* | transpose
5 0 4
5 0 3
7 1 4
1 1 0

Note you can set input and output field separators if you wish to keep format (I guess they are tab separated right now).

Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 1
    If you have it available (BSD variants, at least), `rs` can also be used to transpose. `awk 'FNR==4' f*.txt | rs -T` – jas Aug 11 '15 at 09:35
  • @jas interesting, I didn't know this tool. It is a pity, though, that `yum install rs` does not find anything in my computer : ( – fedorqui Aug 11 '15 at 09:37
  • 1
    Indeed, `rs` looks to be the opposite of portable! Mac OS X has it so I thought it worth mentioning, but for anything other than a one-off on a compatible system your works-everywhere script is the way to go. – jas Aug 11 '15 at 10:17
  • 1
    `+1` and I deleted my answer as it was very similar (mainly I just pulled the `FNR==4` inside the awk script). One thing to note is that `(j – Ed Morton Aug 11 '15 at 15:08
  • 1
    @EdMorton oh, thanks a lot for the suggestions! I will introduce them and deploy the changes, because I am using this script in many answers now : D (Please keep the comment so I can revisit later!) – fedorqui Aug 11 '15 at 16:12
2

awk 'FNR == 4 {print}' will print the fourth row from a text file.

You can use the redirection operator > and concatenation operator >> to append the data from different files.

Deepu
  • 7,592
  • 4
  • 25
  • 47
1

If your data is regular, this is another way of transposing

tr ' ' '\n' <file | pr -"$n"ts" "

where n is the number of rows in your file (columns in transposed version) n can be assigned as

 n=$(wc -l file | cut -d" " -f1)

Your script can be simplified to

 awk 'FNR==4' ifile*.txt > temp
 n=$(wc -l temp | cut -d" " -f1)
 tr ' ' '\n' <temp | pr -"$n"ts" " > ofile.txt
karakfa
  • 66,216
  • 7
  • 41
  • 56