0

I have two files I am trying to read line by line, but I only want to continue reading from only file or the other on any given iteration of a loop. (I am also unsure how to check for EOF). Here is my pseudocode:

#initialize variables
line1=read <file1.txt
line2=read <file2.txt

#compare lists
while true
do
    #check if there is a match
    if [[ "$line1" == "$line2" ]]
    then
        echo match
        break
    elif [ "$line1" -lt "$line2" ]
    then
       line1=read <file1.txt    # <-SHOULD READ NEXT LINE OF F1
    else
       line2=read <file2.txt    # <-SHOULD READ NEXT LINE OF F2
    fi

    #Check for EOF
    if [[ "$line1" == EOF || "$line2" == EOF ]] 
    then
        break
    fi
done

Obviously, as it stands now, this would continue reading just the first line of F1 and F2. Any help would be greatly appreciated!

WarBro
  • 305
  • 2
  • 10
  • Maybe a duplicate? https://unix.stackexchange.com/q/26601/156990 –  Aug 14 '17 at 16:43
  • I don't think so. Assuming my files were: File1.txt: A1 A2 A3 File2.txt: B1 B2 B3 There are tons of results for reading two files in parallel i.e. A1 B1 A2 B2 A3 B3 but I would like the ability to possibly get A1 A2 B1 A3 *exit* or any other combination of orderings of lines from A and B... – WarBro Aug 14 '17 at 16:53
  • `read` doesn't return or output a value (and if it did, the correct syntax would be `line1=$(read < file1.txt)`. Rather, it takes as an argument the name of the variable to assign a value to: `read line1 < file1.txt` – chepner Aug 14 '17 at 17:26
  • Aside: Are you trying to do a merge sort? `sort -m` will do that out-of-the-box. – Charles Duffy Aug 14 '17 at 17:38
  • btw, in addition to the syntax given in @chepner's answer (redirections at the bottom of a block, loop, or similar), you can also `exec 3 – Charles Duffy Aug 14 '17 at 17:38

1 Answers1

1

You need to open each file once, so that you don't reset the file pointer before each read. read will have a non-zero exit status any time it tries to read past the last line of a file, so you can check for that to terminate the loop.

{
  read line1 <&3
  read line2 <&4

  while true; do
    #check if there is a match
    if [[ "$line1" == "$line2" ]]; then
      echo match
      break
    elif [ "$line1" -lt "$line2" ]; then
      read line1 <&3 || break
    else
      read line2 <&4 || break
    fi
  done
} 3< file1.txt 4< file2.txt
chepner
  • 497,756
  • 71
  • 530
  • 681