Reputation: 9036
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
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
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
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
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
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