Прочитайте змінну в bash зі значенням за замовчуванням


191

Мені потрібно прочитати значення з терміналу в скрипті bash. Я хотів би мати можливість вказати значення за замовчуванням, яке може змінити користувач.

# Please enter your name: Ricardo^

У цьому сценарії підказка "Будь ласка, введіть своє ім'я:" за замовчуванням - "Рікардо", а курсор буде після значення за замовчуванням. Чи є спосіб це зробити в баш-скрипті?

Відповіді:


280

Ви можете використовувати розширення параметрів, наприклад

read -p "Enter your name [Richard]: " name
name=${name:-Richard}
echo $name

Включення значення за замовчуванням у підказку між дужками є досить поширеною умовою


7
Я в кінцевому підсумку робив щось на основі цього. Читання в змінну temp, inputа потім використання name=${input:-$name}.
Рікардо Марімон

41
Це фактично не відповідає на питання. Значення за замовчуванням повинно відображатися у підказці.
Доктор Персона Особа II

3
і що буде name=${!input:-$name}робити?
Гаррі Лі

8
@ Dr.PersonPersonII - ви можете додати значення за замовчуванням, зробивши щось подібне: read -p "Введіть ім'я віддаленого хоста [$ remote_host_default]:" remote_host remote_host = $ {remote_host: - $ remote_host_default}
Dobler

4
$1стає${1:-some_default_string}
ThorSummoner

160
read -e -p "Enter Your Name:" -i "Ricardo" NAME

echo $NAME

1
Чудова відповідь! Я просто хочу зазначити, що у мене виникли проблеми з цим, тому що я не бачив пробілу між "Рікардо" та NAME, але одного разу я зрозумів це ... магія ! Дякую!
Містер Міккель

40
на жаль -i не є правильним варіантом для OSX 10.7
визначено

3
@BrianMortenson Ви можете оновити Баш з допомогою доморощеного: stackoverflow.com/questions/16416195 / ...
antonagestam

2
Ця відповідь показує , як зробити цю роботу на OS X (Bash 3.x): stackoverflow.com/questions/22634065 / ...
Christoph Petschnig

3
Зауважте лише, що, -eздається, обов'язково, -iщоб реально працювати
MestreLion

48

У Bash 4:

name="Ricardo"
read -e -i "$name" -p "Please enter your name: " input
name="${input:-$name}"

Це відображає ім'я після відповідного запиту:

Please enter your name: Ricardo

з курсором в кінці імені та дозволяє користувачеві редагувати його. Останній рядок необов’язковий і змушує ім'я бути початковим за замовчуванням, якщо користувач стирає введення або за замовчуванням (подаючи нуль).


Неможливо використовувати bash4, оскільки це нестандартно в дистрибутивах debian. Мені потрібно щось, що буде працювати без особливих клопотів.
Рікардо Марімон

1
немає необхідності в останньому рядку коду, просто використовувати nameзамість inputв readкоманді.
РНК

1
@RNAer: Використовуючи додаткову змінну, значення $nameзберігається, якщо користувач видаляє запропоноване значення (і таким чином вводить нульовий рядок). Все залежить від вашої потреби. Я відповів стільки ж у своїй відповіді. Ти маєш рацію, що я міг би бути більш чітким і сказав, що якби не використовувався необов'язковий рядок, то змінна могла б бути name.
Призупинено до подальшого повідомлення.

1
@DennisWilliamson: Ви праві. Це хороша практика, якщо цього хочеться.
РНК

16

Код:

IN_PATH_DEFAULT="/tmp/input.txt"
read -p "Please enter IN_PATH [$IN_PATH_DEFAULT]: " IN_PATH
IN_PATH="${IN_PATH:-$IN_PATH_DEFAULT}"

OUT_PATH_DEFAULT="/tmp/output.txt"
read -p "Please enter OUT_PATH [$OUT_PATH_DEFAULT]: " OUT_PATH
OUT_PATH="${OUT_PATH:-$OUT_PATH_DEFAULT}"

echo "Input: $IN_PATH Output: $OUT_PATH"

Проба зразка:

Please enter IN_PATH [/tmp/input.txt]: 
Please enter OUT_PATH [/tmp/output.txt]: ~/out.txt
Input: /tmp/input.txt Output: ~/out.txt

Мені це подобається, тому що слід за умовами, які я бачу у багатьох скриптах оболонок, де значення за замовчуванням знаходиться у квадратних дужках перед двокрапкою. Дякую!!!
морфатичний

16

Я знайшов це питання, шукаючи спосіб представити щось на кшталт:

Something interesting happened.  Proceed [Y/n/q]:

За допомогою наведених вище прикладів я вивів це:

echo -n "Something interesting happened.  "
DEFAULT="y"
read -e -p "Proceed [Y/n/q]:" PROCEED
# adopt the default, if 'enter' given
PROCEED="${PROCEED:-${DEFAULT}}"
# change to lower case to simplify following if
PROCEED="${PROCEED,,}"
# condition for specific letter
if [ "${PROCEED}" == "q" ] ; then
  echo "Quitting"
  exit
# condition for non specific letter (ie anything other than q/y)
# if you want to have the active 'y' code in the last section
elif [ "${PROCEED}" != "y" ] ; then
  echo "Not Proceeding"
else
  echo "Proceeding"
  # do proceeding code in here
fi

Сподіваємось, що це допоможе комусь не придумати логіку, якщо вони зіткнуться з тією ж проблемою


Дуже хороша. Можна навіть трохи вдосконалити повторення питання, якщо хтось просто вводить «k» чи щось інше, ніж заданий вибір.
erikbwork

1
Я щойно написав цей коментар після подряпаного свербежу. Тепер у мене є функція оболонки, яка включає вищезазначене, і я, як правило, використовую це. Шелл, здається, не замикається добре, тому я намагаюся цього уникати. Я можу перевірити результат своєї функції та спробувати ще одну спробу, але в основному я пишу інструменти для адміністрування, де все може піти не так, тому я хочу, щоб адміністратор міг чисто зупинити скрипт у будь-якій точці.
sibaz

11

Я тільки що використовував цю схему, яку я віддаю перевагу:

read name || name='(nobody)'

6
name=Ricardo
echo "Please enter your name: $name \c"
read newname
[ -n "$newname" ] && name=$newname

Встановити за замовчуванням; роздрукувати його; читати нове значення; якщо є нове значення, використовуйте його замість за замовчуванням. Існують (або були) деякі зміни між оболонками та системами щодо придушення нового рядка в кінці підказки. Нотація '\ c', здається, працює на MacOS X 10.6.3 з 3.x bash і працює на більшості варіантів Unix, отриманих із System V, використовуючи оболонки Bourne або Korn.

Також зауважте, що користувач, ймовірно, не усвідомлює, що відбувається за лаштунками; їх нові дані будуть введені після імені, яке вже є на екрані. Можливо, краще відформатувати його:

echo "Please enter your name ($name): \c"

printfє більш портативним ніжecho
ghostdog74

3
@ ghostdog74: можливо так; ті з нас, хто вивчив програмування оболонок понад 25 років тому, важко розробили, яка з наших практик все ще актуальна. Все частіше виглядає так, що баш переписав майже все. Я знаю, що printf вже деякий час є командою - я дуже рідко використовую її, хоча (напевно, - ніколи?). У мене складається враження, що я повинен заткнутись на оболонці, поки не буду (знову) вивчати башти. 'Це смішно; програмне забезпечення, над яким я працюю, має сценарії оболонки, які не працюють добре - але проблема не є базовими. Мене просто if (test -z "$xxx"); ...надокучає виправити ' ' та інші C-символіки.
Джонатан Леффлер

Я вражений, що підтримка bash \c, оскільки він також підтримує echo -n! Однак вам доведеться додати, -eщоб отримати баховий відгомін для інтерпретації втечі. Я здогадуюсь \cпро речі, які залишилися echo -e "Syntax slightly off\c, but I've learned so much from what you've shared. Thanks, @JonathanLeffler!"
невимовленими

1
#Script for calculating various values in MB
echo "Please enter some input: "
read input_variable
echo $input_variable | awk '{ foo = $1 / 1024 / 1024 ; print foo "MB" }'

3
будь-ласка, додайте пояснення до своєї відповіді.
Суфіян Горі

-1

Параметр -e і -t не працює разом. Я спробував кілька виразів, і результатом став наступний фрагмент коду:

QMESSAGE="SHOULD I DO YES OR NO"
YMESSAGE="I DO"
NMESSAGE="I DO NOT"
FMESSAGE="PLEASE ENTER Y or N"
COUNTDOWN=2
DEFAULTVALUE=n
#----------------------------------------------------------------#
function REQUEST ()
{
read -n1 -t$COUNTDOWN -p "$QMESSAGE ? Y/N " INPUT
    INPUT=${INPUT:-$DEFAULTVALUE}
    if  [ "$INPUT" = "y" -o "$INPUT" = "Y" ] ;then
        echo -e "\n$YMESSAGE\n"
        #COMMANDEXECUTION
    elif    [ "$INPUT" = "n" -o "$INPUT" = "N" ] ;then
        echo -e "\n$NMESSAGE\n"
        #COMMANDEXECUTION
    else
        echo -e "\n$FMESSAGE\n"
    REQUEST
    fi
}
REQUEST

Ваша відповідь не має великого відношення до питання, чи не так?…
gniourf_gniourf

це робота навколо використання параметра -e та -t. ця кодова лінія (-e та -i за значенням за замовчуванням): read -e -p "Введіть своє ім'я:" -i "Ricardo" NAME не працює з countdownntimer (-t)
speefak

Так, але це не задається питанням, чи не так?
gniourf_gniourf

3
Що ви можете зробити - це задати нове запитання і відповісти на нього самостійно ;). Це дозволено на SO! але ми не хочемо забруднювати інші питання незв'язаними речами.
gniourf_gniourf
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.