Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a text file full of several hundred lines of sequences like this:


    b 29.
    b 52.
    c 84.
    c 83.
    c 94.
    c 93.
    c 61.
    b 38.
    c 81.
    c 92.
    c 28.
    c 37.
    c 27.

    lara@batcuter:~/.asd/a-new-way-of-studying-go$ wc -l game7
    271 game7

and the following script, which separates a text file into two files, one of which consists of odd-numbered lines and one of which consists of even-numbered lines, then reads both files into a while IFS loop, printing a line from each at a time:

#/bin/bash
#testing liquor-where-twin-twas-born

awk '{print>"line-"NR%2}' $@

while IFS= read -r lineA && IFS= read -r lineB <&3; do
  echo "$lineA";
  echo "$lineB" 
done <line-1 3<line-0

which unfortunately gives something not quite the same as the input file, due to the fact that one file was one line longer than the other.


    lara@batcuter:~/.asd/a-new-way-of-studying-go$ testing-liquor game7 > test
    lara@batcuter:~/.asd/a-new-way-of-studying-go$ diff test game7
    270a271
    > b 7.

Obviously, since the file is 271 lines long, splitting it in half yields two files, one of which is 136 lines, and one of which is 135 lines. I need to fix the IFS while loop to return zero differences. At first, I thought using read ... || read ... would help. But actually, that just bloated the output, inserting more than a single a newline between each entry, and shaving off the last line (the line that ended up in the file with the odd number of lines), as did all the other solutions I tried.

share|improve this question
add comment

1 Answer

up vote 2 down vote accepted

Tell the person who suggested || that he's an idiot. Using || makes the snippet read all the lines from fileA first, then all the lines from fileB, because as long as read lineA returns true, read lineB is not executed. Instead, call read both times, saving the return status, then test the return statuses.

while
    IFS= read -r lineA; statusA=$?
    IFS= read -r lineB; statusB=$?
    [ $statusA -eq 0 ] || [ $statusB -eq 0 ]
do …

You can go on to test $statusA and $statusB inside the loop if you need to know whether a file has run out (the line contents will be empty, but this is not distinguishable from an empty line).

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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