awk to transpose every 7 rows into columns

input:

a1
a2
a3
a4
a5
a6
a7
b1
b2
b3
..
b7
..
z1
..
z7

Desired Output:

a1 a2 a3 a4 a5 a6 a7
b1 b2 b3 ............ b7
...
z1 ..................... z7

In need of help from Gurus to transpose every 7 rows into column fields. Thanking you in advance.

awk 'ORS=NR%7?FS:RS' infile
1 Like

works perfectly.. :b:

i tried this but no luck:

awk 'NR==7{a=$1;next}{a=a$1" "}END{print a}'

Hm ..., it should be something like this:

awk '{
  r = length(r) ? r OFS $0 : $0 
  }  
!(NR % 7) {
  print r
  r = x
  }' infile
1 Like

Your 1-liner works perfectly!

awk 'ORS=NR%7?FS:RS' infile

I was simply trying to understand how the NR thingy works.. Thanks again!

I've understood, the second one just somehow follows your style.

Consider the following:

zsh-5.0.0[t]% cat infile 
a1
a2
a3
a4
a5
a6
a7
b1
b2
b3
b4
b5
b6
b7
z1
z2
z3
z4
z5
z6
z7
zsh-5.0.0[t]% awk '{ 
  printf "NR is %d, NR % 7 returns %d <--%s\n", 
    NR, NR % 7, NR % 7 ? " true" : "-- false" 
    }' infile
NR is 1, NR % 7 returns 1 <-- true
NR is 2, NR % 7 returns 2 <-- true
NR is 3, NR % 7 returns 3 <-- true
NR is 4, NR % 7 returns 4 <-- true
NR is 5, NR % 7 returns 5 <-- true
NR is 6, NR % 7 returns 6 <-- true
NR is 7, NR % 7 returns 0 <---- false
NR is 8, NR % 7 returns 1 <-- true
NR is 9, NR % 7 returns 2 <-- true
NR is 10, NR % 7 returns 3 <-- true
NR is 11, NR % 7 returns 4 <-- true
NR is 12, NR % 7 returns 5 <-- true
NR is 13, NR % 7 returns 6 <-- true
NR is 14, NR % 7 returns 0 <---- false
NR is 15, NR % 7 returns 1 <-- true
NR is 16, NR % 7 returns 2 <-- true
NR is 17, NR % 7 returns 3 <-- true
NR is 18, NR % 7 returns 4 <-- true
NR is 19, NR % 7 returns 5 <-- true
NR is 20, NR % 7 returns 6 <-- true
NR is 21, NR % 7 returns 0 <---- false

NR is the number of the current record.
So we manipulate the builtin variable ORS (the Output Record Separator).
When the expression returns 0, false, we set it to the default value of RS (input Record Separator): a newline,
otherwise, we set it to the current (in this case, the default) value
of FS (Field Separator) - a single space.

1 Like

if you have Ruby on your system

x = File.open("file").readlines.map(&:chomp)
x.each_slice(7) { |y|  puts y.join(" ") }

output

# ruby test.rb 
a1 a2 a3 a4 a5 a6 a7
b1 b2 b3 b4 b5 b6 b7
z1 z2 z3 z4 z5 z6 z7

Hi.

$ paste - - - - - - - < data1
a1	a2	a3	a4	a5	a6	a7
b1	b2	b3	b4	b5	b6	b7

See man paste for details.

Best wishes ... cheers, drl

If it is exactly a multiple of 7, below simple 'sed' should be ok for you.

sed -n '{N;N;N;N;N;N;s/\n/ /g;p}' a

If it is somehow not multiple of 7, use below awk.

awk '{
str=$0
pre_nr=NR
for(i=0;i<=5;i++){
 getline a
 if(NR!=pre_nr)
  str=sprintf("%s %s",str,a)
  pre_nr=NR
}
print str
}' your file

or below python

a=[]
with open("a.txt") as file:
 for line in file:
  line=line.replace("\n","")
  if len(a)==3:
   print(" ".join(a))
   a=[line]
  else:
   a.append(line)
if a:
 print(" ".join(a))

of course, perl is another good candidate

while(<DATA>){
    chomp;
    if($.%7==0){
        print $_,"\n";
    }
    else{
        print $_," ";
    }
}

__DATA__
1
2
3
4
5
6
7
8
9
10

Or just use pr
...will also work if it is not an exact multiple of 7 :

pr -7at <yourfile
$ seq 1 17 | pr -7at
1         2         3         4         5         6         7
8         9         10        11        12        13        14
15        16        17

Just the use the relevant options man pr

The separator can also be changed with the -s option if needed pr -7ats' ' <yourfile

Hi All,

I have a data coming in some text file as below:

                   .     351706    5861.8       0.026        0.012       12.584        0.026       0.012      12.582      0.000      0.000      0.000

Now i need the data to be transposed as below in Shell.

351706
5861.8
0.026
0.012
12.584
0.026
0.012
12.582
0.000
0.000
0.000

Please advise

xargs -n1 <yourfile