0

I have input file like below

1
2
3
4
5
6
7
8
9
10

I need output like below

1 2
3 4 5
6 7
8 9 10

Meaning first two lines to be joined together and then the next three lines to be also joined together.

  • 1
    What’s the logic for combining the lines? – Jeff Schaller Jan 5 '18 at 18:20
  • And what about the capitalization? your code does something different from your desired output. – Jeff Schaller Jan 5 '18 at 18:22
0

A double awk appproach:

$ awk '{printf("%s",$0 (NR%5==0?ORS:":"))}' file1 |awk -F':' '{print $1,$2;print $3,$4,$5}'
1 2
3 4 5
6 7
8 9 10

Lines are first joined in groups of five,each line joined with : symbol.

Solution work even if lines contain more words

$ cat file2
this is line 1
this is line 2
this is line 3
this is line 4
this is line 5
this is line 6
this is line 7
this is line 8
this is line 9
this is line 10

$ awk '{printf("%s",$0 (NR%5==0?ORS:":"))}' file2 |awk -F':' '{print $1,$2;print $3,$4,$5}'
this is line 1 this is line 2
this is line 3 this is line 4 this is line 5
this is line 6 this is line 7
this is line 8 this is line 9 this is line 10
2

I can also do the job with paste:

$ seq 10 | paste -s -d $' \n  \n'
1 2
3 4 5
6 7
8 9 10
$ 

bash was used by me here (for $'\n'). And seq 10 was to reproduce your input:

$ seq 10
1
2
3
4
5
6
7
8
9
10
$
  • 1
    The point of the question is to read and combine lines from data inside a file - not to generate a litteral sequence 1 to 10. The real file can contain data from a to z, or words, or whatever. – George Vasiliou Jan 6 '18 at 9:56
  • 1
    @GeorgeVasiliou yes, my answer is about reading and combining arbitrary lines from a file according to the stated rule. You've not understood something. Check and apply my paste command to such a file :) (but my answer is bad because it doesn't use awk) – imz -- Ivan Zakharyaschev Jan 6 '18 at 13:27
  • 1
    No, it does apply on fields (split by whitespaces) not lines. – αғsнιη Jan 6 '18 at 13:38
  • @αғsнιη Oh, was I wrong? Would paste use the fields split by spaces instead of lines?.. No, probably, my command does the right thing; I've just tried an input with spaces: { echo 1 a; echo 2 b; echo 3 c; echo 4 d; echo 5 e; echo 6 f; } | paste -s -d$' \n \n' The output is OK. – imz -- Ivan Zakharyaschev Jan 8 '18 at 6:48
1
#!/usr/bin/awk -f

BEGIN { maxlines=2 ; lc=0 }

{ outputline=outputline " " $0; lc++ }

lc % maxlines == 0 {
  sub(/^ /,"",outputline); # strip unwanted leading space
  print outputline;

  outputline="";
  lc=0;
  maxlines = 5 - maxlines; # flip-flop: 5-2=3, 5-3=2
}

This alternates between joining & printing either 2 or 3 consecutive lines.

Output:

1 2
3 4 5
6 7
8 9 10

or with the original input data:

Unix Linux
Solaris AIX Sco

Alternatively, using an array. awk doesn't have a join() function so we have to provide one.

#!/usr/bin/awk -f

BEGIN { maxlines=2 ; lc=0 }

function join(sep,array,       i) {
  result=array[1];
  for (i=2;i<=length(array);i++) result = result sep array[i];
  return result
};

{ lines[++lc]=$0 }

lc % maxlines == 0 {
  print join(" ", lines);
  delete lines;

  lc=0;
  maxlines = 5-maxlines
}
0

Simply do the job with below awk:

awk -v step=3 '{l=(!l)?l$0:l" "$0} ++seen==2 && step==3{print l;step++;l=seen=""}
    seen==3{print l;step--;l=seen=""}' infile

Output:

1 2
3 4 5
6 7
8 9 10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.