This site is now 100% read-only, and retired.

XML logo

bash read/readline prepopulation questions
Posted by drgraefy on Tue 4 Mar 2008 at 04:53
Tags: ,

So I'm trying to figure out how to prepopulate the prompt for the bash read function with text that could be edited and then passed to the readline output. For some reason I'm having an exceptionally hard time figuring out how to do this. It's either not possible, or I'm just having no luck. For example

The read help says that "One line is read from the standard input", but that doesn't actually seem to be the case:

servo:/tmp/cdtemp.VI3235 0$ foo=
servo:/tmp/cdtemp.VI3235 0$ read -e -p : foo
:asdf
servo:/tmp/cdtemp.VI3235 0$ echo $foo
asdf
servo:/tmp/cdtemp.VI3235 0$ foo=
servo:/tmp/cdtemp.VI3235 0$ echo -n asdf | read -e -p : foo
servo:/tmp/cdtemp.VI3235 1$ echo $foo

servo:/tmp/cdtemp.VI3235 0$ echo asdf >bar
servo:/tmp/cdtemp.VI3235 0$ read -e -p : foo < bar
servo:/tmp/cdtemp.VI3235 0$ echo $foo
asdf
servo:/tmp/cdtemp.VI3235 0$

This appears to indicate that read can accept input from a file, but not from a pipe. Why would that be?

Does anyone know how to prepopulate a read or readline prompt? Maybe it's not possible with read, but with some other function? It must be possible if I were to code it in C or something, cause plenty programs that do stuff like this (take the emacs mini-buffer, for instance).

 

Comments on this Entry

Re: bash read/readline prepopulation questions
Posted by drgraefy (216.254.xx.xx) on Tue 4 Mar 2008 at 18:55
[ View Weblogs ]

so I notice that the "echo -n foo | read.." line produces an error, and the redirect from file does not. read is probably complaining about the lack of newline in the echo bit, which is presumably why it's not returning the stdin into the output variable.

anyway, it's still a real shame as far as I'm concerned, since it means that the bash read is probably not able to do what I want: prepopulate a read input field with data. still looking for other ideas, if they're out there.

[ Parent ]

Re: bash read/readline prepopulation questions
Posted by mcortese (213.70.xx.xx) on Fri 7 Mar 2008 at 11:53
[ View Weblogs ]

Yes, read cannot do what you need. I suggest you simulate the pre-seeding with the ${x:-y} syntax.

myownread() {
        local x
        echo >&0 -e "$1$2\e[A"
        read >&0 -p "$1" x
        eval "$3='${x:-$2}'"
}

Then use it like this:

# Use:
# myownread PROMPT PRESEED VAR
myownread "Question? " "yes" aaa
echo $aaa

The above function works with bash and sh.

The only problem is that the \e[A sequence that forces the cursor up one line is terminal-specific (you can find the sequence that fits your term by pressing Control-V then the Up key).

[ Parent ]

Re: bash read/readline prepopulation questions
Posted by drgraefy (74.66.xx.xx) on Fri 7 Mar 2008 at 13:50
[ View Weblogs ]

That is really interesting, mcortese, and very clever. Thanks very much for the tip. It doesn't do exactly what I want, but it is a very interesting "simulation", as you say.

I thought about the problem more (with dkg), and realized that it's not an easy problem. the readline function has a fairly obtuse way to preseed the command line. it can't really be preseeded from stdin because it's trying to read the user input from stdin as well.

[ Parent ]

Re: bash read/readline prepopulation questions
Posted by endecotp (86.6.xx.xx) on Sat 8 Mar 2008 at 23:39
[ View Weblogs ]
I recall much frustration trying to understand why something|read didn't work, and what to use instead. I have two alternatives:

something > /tmp/foo
read < /tmp/foo

or

read <<EOF
`something`
EOF

[ Parent ]

Re: bash read/readline prepopulation questions
Posted by Anonymous (81.255.xx.xx) on Wed 11 Jun 2008 at 15:33
Here is a third alternative which has the advantage to be a one liner. It is a bashism that makes a command's stdout wrapped into a file.

read < <(something)

The idiom is "<( command )" that you can put instead of a filename.

Still there is something that I miss with read and pipes: the following do displays the content of the file, and was fed to read via a pipe.

cat file | while read a; do echo $a ; done

[ Parent ]