zhong yi
zhong yi

Reputation: 1

Bash scripting - read command is not executed in case structure or if else statement

I have a $empIc which is a variable input by the user. I try to read some details from a text file and do checking on variable $ic. If the input does not match, script file invalidic will be executed where it let the user to choose to reenter the input or back to menu. However, the read command in the invalidic script is never executed and resulted in an infinite loop.

 while IFS=':' read -r dep ic name phone email gender birthDate jobTitle joinDate
 do
  if [ "$empIc" = "$ic" ]
  then
    echo -n "Employee Name : $name"; echo
    echo -n "Job Title     : $jobTitle"; echo
    echo -n "Department    : $dep"; echo 
    break
  else
    match=0
  fi
  case $match in
  0) echo "No such record!"; ./invalidic; break;;
  *) 
  esac
done <Employee.txt

This is the code for invalidic script file:

#!/bin/bash

while true
do
  echo "========================================="
  echo "1. Enter Performance Review again"
  echo "2. Back to Human Resource Management Menu"
  echo "========================================="
  echo "What would you like to do? Please enter choice in number: "; read action
  case $action in
  1) ./task4_main; break;;
  2) ./task1_menu; break;;
  *) echo "Please enter 1 for Performance Review, 2 to back to Human Resource Management Menu"
  esac
done

This is the output I get when the input does not match with data stored

Upvotes: 0

Views: 184

Answers (1)

Gordon Davisson
Gordon Davisson

Reputation: 125798

The immediate problem is that invalidic is run inside the while ... read ... done <Employee.txt loop, so it's reading from the Employee.txt file instead of the terminal. But that's a result of another problem: you presumably want to run invalidic if there's no match for $empIc in the Employees.txt file, but the current script runs it if the first line in Employees.txt doesn't match. It also sort-of tries to run it for each and every non-matching line, but since it never gets past the first one that doesn't happen.

You need to wait until the loop has finished checking each line in the Employees.txt file, and if it gets to the end of that without finding a match then you should run invalidic. That is, do something like this:

match=0   # No match found *yet*, because we haven't started looking

while IFS=':' read -r dep ic name phone email gender birthDate jobTitle joinDate
 do
  if [ "$empIc" = "$ic" ]
  then
    echo "Employee Name : $name"    # Don't use `echo -n`, then `echo` to add a newline. Just skip the -n
    echo "Job Title     : $jobTitle"
    echo "Department    : $dep" 
    match=1    # Found a match
    break
  fi
done <Employee.txt

# If we *still* haven't found a match (now that we've now scanned the
# entire file) then there isn't a match there.
case $match in
  0) echo "No such record!"; ./invalidic;;
  *) 
esac

Actually, I'd replace that last case with a simple if [ "$match" = 0 ] -- you don't need the power and complexity of case here, and IMO an if is the better choice.

Note: I'm also a bit worried that you're using script execution like GOTOs. Inside invalidic, you can run either task4_main or task1_main, both of which sound like main tasks, not subtasks of an invalid ID handler. When you run something like ./somescript, you really should be running a subtask, not just that that's the next logical thing to do.

Upvotes: 2

Related Questions