Bash: Як вивести команду в наступний рядок для користування користувачем?


2

У сценарії bash я хочу вивести команду наприкінці, тому користувачеві потрібно натиснути лише Enterпісля закінчення мого сценарію для виконання цієї команди.

Наприклад, користувачеві необхідно виконати команду з певними параметрами. Замість того, щоб вводити його самостійно, мій скрипт виводить команду з параметрами в їх командний рядок, а потім виходить. На цьому мій сценарій закінчений. Користувач бачить нове підказку із командою «попередньо записаною» до нього.

Цей gif повинен дати уявлення про те, про що я говорю:

приклад

Я бачив цю поведінку в декількох програмах, таких як hstr та qfc , і думаю, що навіть стандартний зворотний пошук шукає це.

Я шукав у Google усе, що я міг придумати, але не можу знайти відповіді.


Вирішення питання: чи буде для вас щось подібне повторювати командний рядок, який ви хочете виконати як останнє твердження вашого сценарію, що чекає на взаємодію з користувачем, який може натиснути enterдля підтвердження (тоді сценарій виконує його та вийти) або перерве (CTRL -C) або змінити / видалити (буде виконуватися нова команда чи нічого)?
Гастур

Ні, команда - це просто "source ~ / .bashrc", що має бути виконано в батьківській оболонці, щоб мати будь-яке використання.
Лассе Мейер

Чи можете ви пояснити краще? У запитанні, яке ви сказали, ви хочете знайти спосіб, щоб ваш скрипт виконував деякі операції та створював команду з параметрами для користувача. Потім ви хочете «заздалегідь записати» команду в CLI, щоб користувачеві довелося лише натиснути клавішу Enter, щоб виконати її. (Попередження про повторний пошук ~/.bahsrc, який буде виконуватися для кожної інтерактивної оболонки bash). BTW запропонованим рішенням (у коментарі вище та у відповіді нижче) було написати команду в сценарії readlineта вийти відразу після взаємодії з користувачем. Без встановлення жодного пакету ...
Гастур

... якщо команда, яку ви хочете створити для користувача, це source somethingвам не потрібно виконувати скрипт, а лише його джерело (і навіть джерело щось буде отримано ..).
Гастур

Команда повинна бути попередньо записана в кліпі, ПІСЛЯ мого сценарію завершено. І сам сценарій неможливо отримати.
Лассе Мейєр

Відповіді:


1

Якщо ви використовуєте X, інструмент xdotool може бути рішенням, включивши в скрипт таку команду, як:

xdotool type command-line-to-display

Якщо новий текст змішається з вихідним сценарієм, можливо, знадобиться деяка акробатика.


Чудово, це єдина відповідь, яка робить саме те, що я хочу без зайвих команд від користувача. І я завжди встановлюю купу матеріалів у сценарії, тому ще один інструмент все в порядку.
Лассе Мейєр

Єдина проблема з цим полягає в тому, що ця команда друкує команду stdout до завершення скрипту, навіть якщо ви перенаправляєте &> в / dev / null. Але врешті-решт правильна команда «заздалегідь написана» так, як я цього хотів.
Лассе Мейєр

Повинен бути спосіб зупинити його вихід на stdout. Джерело доступне і може бути вивчене та модифіковане. Список розсилки користувачів xdotool є xdotool-users@googlegroups.comі може все ще бути активним, хоча веб-сайт востаннє оновлено 25 квітня 2015 року. Ім’я автора - Джордан Сіссел, і його електронний лист очевидно jls at semicomplete.com.
harrymc

3

Додайте ці рядки в кінці вашого bash-сценарію:

MY_COMMAND="ls"
MY_PARAMS=()
read -a MY_PARAMS -p $MY_COMMAND 
exec $MY_COMMAND ${MY_PARAMS[@]}

Це передбачає, що команда, яку ви хочете виконати, - це ls , змініть її так, як вам підходить. Те, що ви вводите, зберігається як масив під назвою MY_PARAMS , ініціалізований першим рядком; Потім команда виконується шляхом повторення команди з подальшим розширенням змінної масиву, що означає всі її елементи. Вищезазначене не залежить від того, скільки елементів ви передаєте вашій команді. Команда оболонки exec замінює оболонку даною командою, ефективно закінчуючи ваш сценарій.

Редагувати :

Якщо ви хочете додати до свого сценарію повні можливості редагування команд, набагато більше того, що може запропонувати read -e , ви можете зробити наступне: встановити rlwrap , а потім додати наступний код у нижній частині вашого сценарію Bash:

stty -ixon
MYINPUT=()
HISTORY=$HOME/.bash_history
MYCOMMAND="ls"
MYINPUT=$(rlwrap -H $HISTORY -P $MYCOMMAND sh -c 'read REPLY && echo $REPLY')
stty ixon
exec sh -c "${MYINPUT[@]}"

rlwrap - це програма, яка здатна використовувати всі функції лінії читання , на відміну від дуже поганого варіанта Bash read -e . Це дозволяє вказати файл, де шукати можливі завершення (я використовував історію Bash, $ HOME / .bash_history , вище, але ви можете написати власний файл). Крім того, він може бути налаштований (див. Розділ inputrc у посібнику з перегляду рядків ), так що ви можете вибирати Emacs -style та vi -style редагування та дозволяє шукати відповідність вперед ( Ctrl+ r) або назад ( Ctrl+ s) у файлі історії, редагуйте команди та багато іншого.

Я додав опції stty -ixon / set ixon , тому що більшість термінальних емуляторів перехоплюють керуючі послідовності Ctrl+ rі Ctrl+ sі так далі, і ця функція наразі відключає цю функцію.

Крім того , команда , яку ви хочете (я використовував Ls для ілюстративних цілей) попередньо завантажені, і можуть бути виконані як (б'ючи повернення) або змінений з допомогою читання рядка можливостей rlwrap .

Що вище не можна зробити - це відобразити список можливих відповідностей, що дозволяє обирати за допомогою клавіатури. Для цього потрібне деяке програмування BASH (див. Відповідь dirkt ).


1
Але це не "попередньо завантажує" пропозицію в батьківську оболонку, виконуючи сценарій, і ви не можете використовувати звичні функції оболонки, такі як редагування рядка тощо.
dirkt

суть його відповіді полягає в тому, що ви ставитесь до команди як до звичайної рядки до моменту, коли ви її фактично виконуєте.
Сірекс

@dirkt Неправда, є спосіб попередньої завантаження заданої команди (я використовував ls для ілюстрації) в обох версіях.
MariusMatutiae

1

Не повна відповідь, а пояснення побаченого:

Ви можете подивитися на те, як QFC робить це шляхом перевірки qfc.sh . Він використовує особливості двох оболонок: Для zsh , zleкоманди, а для bash - READLINE_LINEзмінної. Також обидва варіанти використовують функцію, яка викликається в оболонці, вони не просто запускають скрипт і роблять цю інформацію доступною при виході.

Зробити це у незалежному від оболонки способі при виході сценарію - цікава проблема. :-)


0

pause?

Командний рядок у Windows має pauseкоманду, яка може робити те, що ви хочете виконати.

Він виводить "Натисніть будь-яку клавішу для продовження ...", але вийти з нього можна уникнути, за допомогою pause > nulчого за замовчуванням переводить власний вихід у нікуди, а не на екран


Дякую, але зовсім не за те, що я мав на увазі. Я додав приклад для уточнення. Також Linux не Windows.
Лассе Мейєр

0

Ось коротка (потворна ?, баггі?) Реалізація з прикладом використання / для bash.

inline.sh:

inline () {
    stty_backup=$(stty -g)
    #I don't know why exactly, I just faced it
    stty sane
    res=$($READLINE_LINE 3>&1 >/dev/tty)
    stty $stty_backup
    READLINE_LINE=$res
    READLINE_POINT=${#READLINE_LINE}
}
#the bind is Alt-!, you can change it
bind -x '"\e!":"inline"'

hello.sh:

#!/bin/bash
echo Do you want:
echo 1 past?
echo 2 present?
echo 3 futur?

read -p "1 or 2 or 3? " r

if [ "$r" = "1" ]; then r="uptime"
elif [ "$r" = "2" ]; then r="date"
elif [ "$r" = "3" ]; then r="fortune fortunes"
else r=""
fi

echo $r >&3

Ваш сценарій повинен бути досить розумним, рядок, який ви хочете повернути за вашим запитом, повинен бути повернутий через fd 3 (див. Inline.sh).

Тепер,

source inline.sh

тип

./hello.sh

натисніть Alt-!

Звичайно, ви можете джерело inline.sh у вашому bashrc.


0

Обхід:

в останньому рядку сценарію ви можете написати щось на зразок:

PrebuildCOMMAND="ls -lrt"             # just as example
echo "That's your command "           # keep your user informed
read -e -p " " -i "$PrebuildCOMMAND"  CMDtoEXECUTE
$CMDtoEXECUTE                         # here you execute what it was answered

Примітка: я зараз зауважую, що це варіант (спрощений) запропонований іншою відповіддю (більш повний).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.