5

What can I do to leave the cursor on the same line of the suggestion in a Bash script?

Bash version = 3.2.51

It's purpose is to suggest a string so that the user should only press Enter.

#!/bin/sh
echo "@@@@@@@@@@
@ Enter the new plarform name [for example: our-platform-7.26-2.17-res4]:
@@@@@@@@@@"
echo "our-platform-7.26-2.17-res4"
read SuggestDefaultPlatform

echo "Stored name: " ${SuggestDefaultPlatform}

which prompts:

@@@@@@@@@@
@ Enter the new plarform name [for example: our-platform-7.26-2.17-res4]:
@@@@@@@@@@ 
our-platform-7.26-2.17-res4
_

where the underscore "_" stands for the cursor.

I don't want to use a "Y/n" logic workaround, assigning a default value to the "SuggestDefaultPlatform" variable

SuggestDefaultPlatform='our-platform-7.26-2.17-res4';

and then prompt a question like:

Are you okay with `'our-platform-7.26-2.17-res4'` as your platform name? [Y/n]...

Instead the user might want to change just a few digits of a prompted suggestion and press Enter. See below the cursor "_" at the end of the "SuggestDefaultPlatform" variable:

@@@@@@@@@@
@ Enter the new plarform name [for example: our-platform-7.26-2.17-res4]:
@@@@@@@@@@ 
our-platform-7.26-2.17-res4_

so that the user can move the cursor, modify the suggestion and/or press Enter.

our-platform-7.26-2.17-res_
our-platform-7.26-2.17-re_
our-platform-7.26-2.17-r_
our-platform-7.26-2.17-_
our-platform-7.26-2.17_
our-platform-7.26-2.1_
our-platform-7.26-2.18-alpha1_

Press Enter.

which prompts:

Stored name: our-platform-7.26-2.18-alpha1
  • 1
    Your question isn't quite clear. You probably want to say read -p 'our-platform-7.26-2.17-res4 ' SuggestDefaultPlatform – devnull Feb 15 '14 at 9:52
  • I tried "read -p" but does not let the user edit the answer. – Mau Feb 22 '14 at 5:25
4

sh (as in the sh language specification) doesn't come with a line editor. Terminal drivers have a rudimentary line editor that allow for backspace and a few other keys to edit the entered line, but generally not arrow keys.

You can insert a default value into the terminal driver input buffer using the TIOCSTI ioctl like:

printf 'Please enter the value: '
value=the-default
perl -MPOSIX -e 'require "sys/ioctl.ph"; tcflush 0,2;
  ioctl(STDIN, &TIOCSTI, $_) or die "$!\n"
    for split "", join " ", @ARGV' "$value"
IFS= read -r value

Upon the read, the content of $value (the-default) will have been inserted as if typed.

Now, if you want a more advanced line editor like provided by libreadline where you can use arrow keys, you can use things like rlwrap (not a standard command though):

value=the-default
value=$(rlwrap -S 'Please enter the value: ' -P "$value" -o cat)

rlwrap is typically used to add a readline-like line editors to applications that don't have one. Above we're adding a line editor to cat, and using it in one-shot mode (-o), so that cat returns after one line is entered (though you can still enter more than one line with Ctrl+V, Ctrl-J like in bash.

If you're ready to use non-standard shells, zsh or bash have builtins for that using their own line editor.

In zsh:

value=the-default
vared -p 'Please enter the value: ' value

In bash:

value=the-default
IFS= read -re -i "$value" -p 'Please enter the value: ' value
  • read: -i: invalid option - I am running version 3.2.51 but that would answer the question. – Mau Feb 22 '14 at 5:56
3

You want to use bash instead of sh and the -e and -i options of its read builtin:

#!/bin/bash -
echo "@@@@@@@@@@
@ Enter the new plarform name [for example: our-platform-7.26-2.17-res4]:
@@@@@@@@@@"
read -i "our-platform-7.26-2.17-res4" -e SuggestDefaultPlatform

echo "you chose $SuggestDefaultPlatform"

From help read in bash:

  -i text   Use TEXT as the initial text for Readline
  -e        use Readline to obtain the line in an interactive shell

So, the -i sets the default value and the -e allows you to enter another or modify it. You don't need the extra echo.

  • 1
    Note that this requires v4 of bash. – bahamat Feb 15 '14 at 21:14
  • read: -i: invalid option - I am running version 3.2.51 but that would answer the question. – Mau Feb 22 '14 at 5:47
2

Short answer: use the -n flag for echo.

Slightly better answer: The default echo behavior is to print each argument to standard out, followed by a newline character. These characters are special in that you don't see them, since they are a basic way of representing output formatting. All sorts exist for tabs, new lines, returns, etc.

It would be extremely tedious if we didn't have an easy way to tell our shell when we wanted to insert things like tabs or newlines. To overcome this, echo defines certain escaped characters to have special meaning. \n means newline, and \t means to output a tab character [link].

In the following example, you can see this in action. I used tr which translates character from one set to another. The output will show a - everywhere that it found a newline:

echo "Hello\nFriends" | tr "\n" "-"
Hello\nFriends-

Notice that we found a newline at the end, since it was automatically added by echo. Now, we can use -e to disable that behavior. Notice there's no dash at the end:

echo -en "Hello\nFriends" | tr "\n" "-"
Hello\nFriends

If you want to make echo output the meaning of escape sequences (like the \n above), use -e:

echo -e "Hello\nFriends"
Hello
Friends
  • True, but irrelevant. The OP wants to load the default value into the variable and allow the user to edit it. Your answer just gives a way to not have a newline, it does not help in saving the value into the variable. – terdon Feb 15 '14 at 13:46
  • I guess I misunderstood - I thought he was saying he wanted to have the input appear on the same line as the prompt. – tdk2fe Feb 17 '14 at 3:17
  • sorry for the misunderstanding.. let me know how can i better my question – Mau Mar 26 '15 at 4:08
2

Newer versions of bash (I believe at least v4) can use readline input and prefill text.

read -e -p "> " -i "our-platform-7.26-2.17-res4" SuggestDefaultPlatform

If bash 4 isn't available, I use rewrap* for this. The -P option lets you prefill the text of the line..

SuggestDefaultPlatform=$(rlwrap -P "our-platform-7.26-2.17-res4" bash -c 'echo -n "> "; read response; echo $response')

In either case, the user can just hit enter to accept the value or can edit the line before submitting. It will look like this:

> our-platform-7.26-2.17-res4_

Where _ is the cursor. You can back up all the way to the o, but the > will remain as a prompt and can't be overridden. Only the text after the prompt is in the variable.


* rlwrap itself may need to be installed as well.

  • rlwrap: command not found - but your answer would answer the question. – Mau Feb 22 '14 at 6:00
  • 1
    I did also already mention that rlwrap may need to be installed separately. In a lot of cases that may be easier than getting a newer version of bash to support read -e. – bahamat Feb 23 '14 at 8:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.