Написание эквивалента функции ввода Python в bash

#bash

#bash

Вопрос:

Я пытаюсь написать простой эквивалент input функции Python в Bash.

Примером в скрипте Python может быть что-то вроде этого:

 s = input('Please input something: ')
  

Я полагаю, что вызов эквивалента Bash будет выглядеть следующим образом:

 s=$(input "Please input something: ")
  

Это реализация, которую я написал:

 function input {
    # $1 is the prompt passed as an argument; in my above example,
    # it would be 'Please input something: '
    printf "%s" "$1"
    read in
    echo "${in}"
    return 0
}
  

При вызове s=$(input "Please enter something: ") приглашение никогда не печатается; вместо этого скрипт Bash просто ожидает ввода пользователем, даже не отображая текст. Нажатие Enter, то есть не ввод, устанавливает s само приглашение. Похоже, что происходит s захват выходных данных из строки printf "%s" "$1" , затем считывание входных данных, которые также отражаются обратно. Я также пытался явно направить приглашение на stdout with printf "%s" "$1" >amp;1 , но безрезультатно.

Как я могу сначала распечатать приглашение, затем захватить ввод и передать его обратно вызывающей функции?

Комментарии:

1. Ответ Джонка правильный, но, тем не менее, чтобы ваше приглашение отправлялось в TTY без захвата, запишите его в stderr, а не в stdout, который также имеет удачное преимущество в том, что по умолчанию он не буферизован, тогда как когда stdout направляется в TTY, он по умолчанию буферизуется по строкам. Кстати, собственные подсказки оболочки также передаются в stderr.

Ответ №1:

Вам повезло. Она уже существует в виде read -p .

 read -p 'Please input something: ' s
  

На всякий случай неплохо IFS= -r также использовать and . IFS= гарантирует сохранение начальных и конечных пробелов. -r сохраняет обратную косую черту, поэтому n не интерпретируется как перевод строки или \ не превращается в .

 IFS= read -rp 'Please input something: ' s
  

Что касается того, почему ваша функция не работает, это потому, что приглашение печатается в стандартный вывод, который фиксируется. Выведите в stderr, чтобы она отображалась.

 input() {
    printf "%s" "$1" >amp;2
    read in
    printf '%sn' "$in"
}
  

Тщательный сценарист будет использовать printf '%sn' вместо echo . Если пользователь вводит -n или -e вы хотите, чтобы они печатались, а не интерпретировались как параметры.