简体   繁体   中英

How to read from user within while-loop read line?

I had a bash file which prompted the user for some parameters and used defaults if nothing was given. The script then went on to perform some other commands with the parameters. This worked great - no problems until most recent addition.

In an attempt to read the NAMES parameter from a txt file, I've added a while-loop to take in the names in the file, but I would still like the remaining parameters prompted for.

But once I added the while loop, the output shows the printed prompt in get_ans() and never pauses for a read, thus all the defaults are selected.

I would like to read the first parameter from a file, then all subsequent files from prompting the user.

What did I break by adding the while-loop?

cat list.txt | 
while read line
do 
  get_ans "Name" "$line"
  read NAME < $tmp_file

  get_ans "Name" "$line"
  read NAME < $tmp_file
done

function get_ans
{
  if [ -f $tmp_file ]; then
    rm $tmp_file

  PROMPT=$1
  DEFAULT=$2

  echo -n "$PROMPT [$DEFAULT]: "
  read ans
  if [ -z "$ans" ]; then
    ans="$DEFAULT"
  fi
  echo "$ans" > $tmp_file
}

(NOTE: Code is not copy&paste so please excuse typos. Actual code has function defined before the main())

You pipe data into your the while loops STDIN. So the read in get_ans is also taking data from that STDIN stream.

You can pipe data into while on a different file descriptor to avoid the issue and stop bothering with temp files:

while read -u 9 line; do
   NAME=$(get_ans Name "$line")
done 9< list.txt

get_ans() {
    local PROMPT=$1 DEFAULT=$2 ans
    read -p "$PROMPT [$DEFAULT]: " ans
    echo "${ans:-$DEFAULT}"
}

To read directly from the terminal, not from stdin (assuming you're on a *NIX machine, not a Windows machine):

while read foo</some/file; do
    read bar</dev/tty
    echo "got <$bar>"
done

When you pipe one command into another on the command line, like:

$ foo | bar

The shell is going to set it up so that bar 's standard input comes from foo 's standard output. Anything that foo sends to stdout will go directly to bar 's stdin.

In your case, this means that the only thing that your script can read from is the standard output of the cat command, which will contain the contents of your file.

Instead of using a pipe on the command line, make the filename be the first parameter of your script. Then open and read from the file inside your code and read from the user as normal.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM