Gery
Gery

Reputation: 9036

Print two lines at the same time

I have this problem, I need to print 2 lines at the same time for the same file, the problem is that it must occur following the row changes in the first column, e.g.:

file: abcd.csv

a,1
a,2
a,3
a,4
a,5
a,6
b,1
b,2
b,3
b,4
b,5
b,6
c,1
c,2
c,3
c,4
c,5
c,6

code:

awk '{ if ( $1 == "a") print $1,$2 } ' FS="," abcd.csv

which prints:

a 1
a 2
a 3
a 4
a 5
a 6

but I need two lines at the same time, because I need to pipe these two rows to an additional call:

1st output (then they will be sent):

a 1
a 2

2nd output (then they will be sent):

a 2
a 3

3rd output (then they will be sent):

a 3
a 4

4th output (then they will be sent):

a 4
a 5

5th output (then they will be sent):

a 5
a 6

and so forth for the other letters in the first column.

I'd appreciate any hints on this,

Upvotes: 1

Views: 3035

Answers (5)

Birei
Birei

Reputation: 36262

I would use the getline() function inside an infinite loop, and break it when first field is different from a character:

awk '
    FNR == 1 {
        while (1) {
            prev_line = $0
            r = getline
            if (r != 1) {
                exit r
            }
            split(prev_line, arr_prev, /,/)
            split($0, arr, /,/)
            if (arr_prev[1] == "a" && arr[1] == "a") {
                printf "%s\n%s\n", prev_line, $0
            }
            else {
                exit 0
            }
            print "============="
        }
    }
' infile

It yields:

a,1 
a,2 
============= 
a,2 
a,3 
============= 
a,3 
a,4 
============= 
a,4 
a,5 
============= 
a,5 
a,6 
=============

UPDATE: To avoid an infinite loop I added a check in the getline() result to exit in end of file or an error.

Upvotes: 1

glenn jackman
glenn jackman

Reputation: 246837

You need to manage this after your awk call:

awk -F, '$1 == "a" {print $1,$2}' abcd.csv | 
while read line1; do
    read line2
    printf "%s\n%s\n" "$line1" "$line2" | additional_call
done

Upvotes: 3

Andrew
Andrew

Reputation: 4751

You say you need to pipe each two lines so some other call, if you produce all the output in one go then you'd still need to split each pair of lines in order to make this other call.

I'd just do the following in bash,

    FILE=abcd.csv; \
    LINES=`wc -l $FILE | cut -d' ' -f1`; \
    for N in `seq 2 ${LINES}`; do \
        head -n${N} $FILE | tail -n2 | awk '{print $1,$2}' FS="," | cat;  \
    done

Replace the last | cat before the done with the call you actually want to make, this will receive each pair of lines.

Upvotes: 1

FuriousGeorge
FuriousGeorge

Reputation: 4681

If you don't need to use awk then a simple python program would suffice:

#!/usr/bin/python

import sys

with open(sys.argv[1], 'r') as f:
    content = f.readlines()

for i in range(len(content)-1):
    if content[i].split(',')[0] == content[i+1].split(',')[0]:
        print content[i]
        print content[i+1]

Upvotes: 1

imp25
imp25

Reputation: 2357

It is unclear from your question what you mean by "two lines at the same time", but the below code will output in two line groups within each letter:

#!/usr/bin/awk -f

BEGIN { FS=","; OFS=","}
{
    count[$1]++;
    rows[$1][count[$1]] = $2;
}
END {
    for(i in count) {
        for(k=1; k<=count[i]-1; k++) {
            print i,rows[i][k]
            print i,rows[i][k+1] 
            print ""
        }
        print ""
            print ""
        }
    }

This code sets the input and output field separator to be a comma. It then creates a 2D hash with the first letter and the line within that letter group as the keys, and the second column as the value.

Finally it goes through the 2D hash for each initial letter and the group row value printing in groups of two within that letter's set.

Output base on your given input:

a,1
a,2

a,2
a,3

a,3
a,4

a,4
a,5

a,5
a,6



b,1
b,2

b,2
b,3

b,3
b,4

b,4
b,5

b,5
b,6



c,1
c,2

c,2
c,3

c,3
c,4

c,4
c,5

c,5
c,6

Upvotes: 1

Related Questions