Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

user input in a shell script 3

Status
Not open for further replies.

LunaPan

Programmer
Jan 13, 2004
25
US
Hi, I need to get some user input using a shell script in unix. The trick is that after the prompt for the input, the old value needs to appear so the user can edit it and then submit. What I want is below:

Please update the following path:
/foo/bar/

Thanks!
 
OK, thanks for that chipper, much easier than I expected. I've got rl working from the command prompt, but any way I try to capture the output from rl in a script, the -p prompt does not appear and none of my typed input appears until I press enter.

I tried newvalue=$(rl -p "..." -d "...") as well as newvalue=`rl -p "..." -d "..."` with no luck. I even tried rl -p "..." -d "..." > temp.txt

Why would this be happening?

Thanks again for your help.
 
LunaPan - does the rl documentation document give you any hints?

Mike

"Deliver me from that bane of civilised life; teddy bear envy."

Want to get great answers to your Tek-Tips questions? Have a look at faq219-2884

 
Not really, the docs concentrate on readline's code, rl is an example program and doesn't really seem to be supported. (The C code for rl is has no internal documentation besides the usual GNU business...)
 
I think I know why this is happening, the prompt is actually being fed into the variable, not the terminal... How to separate the prompt into the terminal and the typed input into my variable???
 
Hmm... strange.


What OS are you using?

Try playing around with the TERM variable and see if that makes anything better. Try a different shell, too.

Did you link the Readline library in statically, or as a shared library? If it's shared, make sure the version you used is one that rl likes.

Try using the linking method you didn't use before, too, and see if that changes anything.


As an alternative, there are also some Perl Readline modules that may work better (or maybe not). If those work, you could write a Perl one-liner to serve as an input function if that doesn't seem like overkill.


Or, hey, if all else fails, read the Readline source, see how it manages to do interactive command line editing, then copy it using tput.
 
Ah. That's no good...

A quick fix might be to use tee to pipe the output into a file, then read the file to get the result...

i.e.
Code:
rl -p"Enter your name: " -d"Bob" |tee tempfile
result=$(tail -1 tempfile)
echo "Hello, $result!"


But what's that -u option to rl.c? That changes the file descriptor it uses to read from the terminal... That could be promising.
 
Almost, this gets the input into my variable, but rl still outputs the value on its own resulting in this:

Enter your name: Bob
Bob
Hello, Bob!

The problem is that the way readline is designed, all the input comes from one fd, and all the output goes to another fd, including the prompt :( The -u changes the instream fd, which does me no good. I would add a -o in the rl source but that wouldn't help either unless I actually modified the readline source as well to change outstreams after showing the prompt ... I may have to figure out how to do that...
 
FINALLY, I have exactly what I want by making a minor change to rl. I made the 3rd line from the bottom
Code:
fprintf (stderr,"%s\n", temp);
sending only the result to standard error. Then in the script I sent the stderr from rl to a file and used your solution for the rest.
Code:
rl -p "Enter your name:" -d "Bob" 2> temp.txt
result=$(tail -1 temp.txt)
echo Hello, $result

Thanks a million for the assist chipper.
 
What about this (untested) ?
result=$(rl -p "Enter your name:" -d "Bob" 2>&1 >/dev/tty)
echo Hello, $result


Hope This Helps, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884 or FAQ222-2244
 
PHV: I tried this at your suggestion and thought it worked at first, but closer inspection of the result shows it is adding a carraige return or something to the result(I tried sedding out \r's \n's and \l's with no luck)

Code:
NEWPATH=$rl -p "Enter your name: " -d "Bob" 2>&1 >/dev/tty)
echo Hello, @${NEWPATH}@

produces...

Enter your name: Bob
@ello, Bob@
 
Whoops, I copied that wrong, it was:

Code:
NEWPATH=$(rl -p "Enter your name: " -d "Bob" 2>&1 >/dev/tty)
echo Hello, @${NEWPATH}@

produces...

Enter your name: Bob
@ello, @Bob
 
You can use Ksh read and print to accomplish the same thing 'rl' does without having to install another program that would need to be maintained. You can remove the 'print -r' line if you don't want to echo your input.

Code:
#!/usr/dt/bin/dtksh

print "Prompt: "
[[ -z $1 ]] && set -- -
for i
do
        if [[ $i != - ]] then
                exec 3< $i
        else
                exec 3<&0
        fi
        IFS=
        while read -u3 -r line
        do
                if [[ $line = "" ]] then
                        break
                fi
                print -r -- "$line"
                break
        done
done
exec 3<&-
 
wow... would you explain that please iknowitall?

Mike

"Deliver me from that bane of civilised life; teddy bear envy."

Want to get great answers to your Tek-Tips questions? Have a look at faq219-2884

 
[[ -z $1 ]] && set -- - # use stdin if no arguments
exec 3< $i # open file
exec 3<&0 # use stdin
while read -u3 -r line #read line
print -r -- "$line" # print line
exec 3<&- #close file
 
And where is the editing stuff (with standard ksh) ?

Hope This Helps, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884 or FAQ222-2244
 
You're not gonna believe this...
Check out vared for zsh...
 
what's that?

Mike

"Deliver me from that bane of civilised life; teddy bear envy."

Want to get great answers to your Tek-Tips questions? Have a look at faq219-2884

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top