Як ввести n повторень цифри в bash, інтерактивно


20

Я хотів би запустити команду

foo --bar=baz <16 zeroes>

Як я можу ефективно набрати 16 нулів *? Якщо я утримую Altі натискаю, 1 6 0це повторить наступну справу 160 разів, а це не те, що я хочу. У emacs я можу використовувати Alt-[number]або Ctrl-u 1 6 Ctrl-u 0, але в bash Ctrl-uвбиває рядок, що набирається в даний момент, і наступний нуль просто додає 0 до рядка.

Якщо я це роблю

foo --bar=baz $(printf '0%.0s' {1..16})

Тоді historyпоказує саме зазначене вище, а не foo --bar=baz 0000000000000000; тобто Баш не веде себе так, як я хочу. ( Редагувати : точка є, я хочу ввести деяку кількість нулів без використання $(...)підстановки команд)

(*) Я припускаю, що технічне визначення "ефективно" - це "з натисканням клавіші O (log n)", бажано, числом натискань клавіш, рівним кількості цифр у 16 ​​(для всіх значень 16) плюс можливо константа; приклад emacs визначає як ефективне цим визначенням.


1
Здається, ви хочете, щоб баш хоч якось know what you want to do. Як складна вкладена команда, як би знати, в яких частинах ви хотіли бачити результат виконання в історії, на відміну від самої команди? Що щодо змінних? Коротше кажучи, bash завжди буде мати codeісторію, а не результат виконання коду.
Невіруючий

@meuh, Altсам по собі не надсилає жодного символу, тому натискання та звільнення alt не матиме жодного ефекту, що bashстосується.
Стефан Шазелас

1
@Unbeliever Роби те, що я маю на увазі, і це буде гаразд
кіт

@Unbeliever: дивіться мою редагування - пункт абзацу, що стосується цього, historyполягає в тому, що я хотів би ввести цифри без використання підстановки команд.
Йонас Келькер

Всякий раз, коли ви хочете, щоб речі вводилися автоматично для вас, AutoKey - це чудова утиліта. З його допомогою ви можете створити підстановку фрази або завершити макроси Python, які виконають майже все, що вам подобається, коли вводиться тригерна фраза або натискається швидка клавіша. Я не включив це як відповідь, оскільки для цього потрібне середовище робочого інтерфейсу графічного інтерфейсу, а решта відповідей - і, таким чином, більш загальноприйнятна.
Джо

Відповіді:


25

Спробуйте

відлуння Alt+1Alt+6Ctrl+V0

Це 6 клавіш (якщо принаймні клавіатура QWERTY США / Великобританія принаймні), щоб вставити ці 16 нулів (ви можете утримувати Altі 1, і 6).

Ви також можете використовувати стандартний viрежим ( set -o vi) та ввести:

відлуння 0 Escx16p

(також 6 ключових штрихів).

emacsЕквівалентний режим і який може бути використаний для повторення більш одного символу ( ) працює , але не в .echo 0Ctrl+WAlt+1Alt+6Ctrl+Yzshbash

Усі вони також працюватимуть zshtcshзвідки це походить). З zsh, ви можете також використовувати прапорці змінних розширень розширення та розширити їх за допомогою Tab:

echo $ {(l: 16 :: 0 :)}Tab

(Очевидно, що набагато більше натискань на клавіші).

З bash, ви можете також bashрозширити свій $(printf '0%.0s' {1..16})з Ctrl+Alt+E. Зауважте, що це дозволить розширити все (не глобуси) на лінії.

Щоб грати в гру з найменшою кількістю натискань клавіш, ви можете прив’язати до якогось ключового віджета, який розширюється <some-number>Xдо Xповторних <some-number>разів. І <some-number>в базі 36 є ще більше її зменшити.

З zsh(зв'язано F8):

repeat-string() {
  REPLY=
  repeat $1 REPLY+=$2
}
expand-repeat() {
  emulate -L zsh
  set -o rematchpcre
  local match mbegin mend MATCH MBEGIN MEND REPLY
  if [[ $LBUFFER =~ '^(.*?)([[:alnum:]]+)(.)$' ]]; then
    repeat-string $((36#$match[2])) $match[3]
    LBUFFER=$match[1]$REPLY
  else
    return 1
  fi
}
zle -N expand-repeat
bindkey "$terminfo[kf8]" expand-repeat

Потім для 16 нулів ви вводите:

відлуння g0F8

(3 натискання клавіш), де gзнаходиться 16в базі 36.

Тепер ми можемо додатково зменшити його до однієї клавіші, яка вставляє ці 16 нулів, хоча це було б обманом. Ми можемо прив’язати F2до двох 0s (або двох $STRING, 0 за замовчуванням), F3до 3 0s, F1F6до 16 0s ... до 19 ... можливостей нескінченно, коли можна визначити довільні віджети.

Можливо, я повинен зазначити, що якщо натиснути і утримувати 0клавішу, ви можете вставити стільки нулів, скільки вам потрібно, лише одним натисканням клавіші :-)


Дякуємо, що надали кілька варіантів для viта інших!
Марк Стюарт

9

Якщо припустити, що ваш термінальний емулятор не змушує натиснути клавішу (наприклад, для переключення вкладок) - звичайний xterm працює - ви можете натиснути Alt-1 6 Ctrl-V 0. Контроль-V потрібен там, щоб розділити число та символ, який потрібно повторити (якби ви повторювали лист, він би вам не знадобився).

(Це функція readline, відома як digit-argument, тому ви повинні мати можливість використовувати bindзміни модифікованих ключів)


1
Дякую, що назва цієї функції корисна, коли люди, як я, натикаються на ці питання. Посилання на посилання, щоб прочитати більше: SO Питання та посібник з
башти

4

У Emacs я зазвичай використовую C-qдля відділення аргументу префікса від цифрного введення.

Bash використовує Ctrl+vзамість C-q, щоб уникнути проблем з контролем потоку XON / XOFF.

Тож можна використовувати Alt+1 Alt+6 Ctrl+v 0.


3

інший варіант - ввести чотири нулі, а потім скопіювати і вставити його ще три рази за допомогою миші. двічі клацніть для вибору, середнім клацанням x 3 для вставки.


Або пограти в гольф / обдурити ще трохи, набравши один нуль, виберіть & вставити, щоб отримати 2; виберіть & вставити, щоб отримати 4; виберіть і вставте до 8, і знову для 16. Це POWerful :)
Jeff Schaller

так, але введення 4 нулів і повторне вклеювання здається мені оптимальним рівнем зусиль проти окупності. все те, що додаткове копіювання та вклеювання здається роботою.
cas

3

Гра з макросами:

Прив’яжіть функціональну клавішу, F8щоб перемножити на два останнє слово (вгору попереднє пробіл) (код клавіші F8, знайдений за допомогою Ctrl-V F8):

$ bind '"\e[19~": "\C-w\C-y\C-y"'

Це можна зробити постійним, надіславши той самий текст ~/.inputrc

$ echo '"\e[19~": "\C-w\C-y\C-y"' >> ~/.inputrc

потім введіть:

відлуння 0F8F8F8F8

щоб отримати 2 ^ 4 рази більше нуля. (ще 5 натискань клавіш).

або введіть:

ехо книгаF8F8F8

щоб отримати 2 ^ 3 книжкових слів.

Ще швидше:

Помножте на 4:

$ bind '"\e[19~": "\C-w\C-y\C-y\C-w\C-y\C-y"'

відлуння 0F8F8

3 натискання клавіш.

Помножте на 8 (те саме число, що і функціональна клавіша)

$ bind '"\e[19~": "\C-w\C-y\C-y\C-w\C-y\C-y\C-w\C-y\C-y"'

ехо 00F8

Ще 3 натискання клавіш.

Чит?

Читайте шляхом множення на 16.

$ bind '"\e[19~": "\C-w\C-y\C-y\C-w\C-y\C-y\C-w\C-y\C-y\C-w\C-y\C-y"'

відлуння 0F8

Лише 2 натискання клавіш. (та ще корисна проста функція)

^^^^^^^^^^^^^^^^ (база 36? Га!) :-P

Просте обман:

$ bind '"\e[19~": "0000000000000000"'

відлуння F8

Всього 1 (так: один ) натискання клавіші.



Зміна прив’язки для ctrl+U:

Надіслати це на адресу ~/.inputrc:

echo '"\C-u": universal-argument >> ~/.inputrc

Перечитайте ~/.inputrcфайл:

ctrl+Xctrl+R

зробіть це як зазвичай в emacs (як хотіли):

foo --bar = baz ctrl+U16 ctrl+U0

7 клавіш (після "налаштування").

Трохи коротше:

Використовуйте за замовчуванням "помножте на 4" "універсального аргументу" і закінчіть

 ctrl+V 0 

foo --bar = baz ctrl+Uctrl+Uctrl+V0

Всього 5 клавіш.

Використання alt+nдоступу до (arg: n)

foo --bar = baz Alt+16Ctrl+V0

Це 6 клавіш, щоб отримати 16 нулів.

Не змінюючи жодної комбінації клавіш:

Якщо у вашому башті є bash C-u kills the currently-being-typed line.
Це тому "\C-u":, що зобов’язаний unix-line-discard.

Але це також може допомогти:
Коли, що є перед тим, як курсор буде стерто, він також розміщується у "kill-ring".

Тож ctrl+uстирає і ctrl+yянки повертає те, що було стерто.
У чистому рядку: Введіть 00стерти його та двічі поверніть його назад 0000.
Повторіть для отримання 00000000(8 нулів), нарешті введіть команду і двічі поверніть назад.

Перший набір (натискання 7 клавіш ctrl):

00 ctrl+Uctrl+Yctrl+Y ctrl+U 

Другий набір (5 клавіш)

ctrl+Uctrl+Yctrl+Y ctrl+U 

Це отримає вісім нулів у кільці стирання, а потім введіть те, що потрібно:

 foo --bar = baz ctrl-Y ctrl-Y 

отримати:

foo --bar=baz 0000000000000000

Отримавши ідею, ви також можете ввести те, що вам потрібно, перейдіть до початку рядка ( ctrl-Y), зробіть так, як вище (до восьми нулів), перейдіть до кінця ( ctrl-E) і потріпніть двічі.

foo --bar = baz ctrl-A00ctrl-Uctrl-Yctrl-Y ctrl-Uctrl-Yctrl-Y ctrl-U ctrl-Ectrl-Yctrl-Y

Це 15 клавіш (поруч із самою командою).
Я не короткий, я знаю, але це працює лише з тим, що було доступно.

Це трохи коротше:

0000 ctrl-U ctrl-Y ctrl-Y ctrl-Y ctrl-Yctrl-A foo --bar = baz

Це 11 ключів


Дивіться редагування моєї відповіді ;-)
Стефан Шазелас

@ StéphaneChazelas Використання макросів? База 36? Тільки в zsh? Хай ... дивіться мою
редакцію

Ну так, база36 була трохи мовою в щоках. Мені подобається, що ти F<n>дублюєш останній <n>раз слова .
Стефан Шазелас

Зауважте, що не всі термінали надсилають одну і ту ж послідовність на F8 (хоча більшість тих, що знаходяться в системах GNU / Linux, все-таки надсилають ^[[19~). Дивіться, "$(tput kf8)"щоб отримати інформацію з бази даних terminfo (або $terminfoхешу zsh).
Стефан Шазелас

@ StéphaneChazelas Так, це правильно. Або просто скористайтесяctrl-v F8
sorontar

2

Введіть варіант відповіді кас

printf '0% .s' {1..16}Enter
а потім скопіюйте та вставте мишу (один раз) за допомогою миші. Можливо, це O (log n), але оскільки це (len (str (n)) + 20), ви можете вважати це неефективним. Але зверніть увагу:

  • Мені вдалося поголити одного персонажа - на моїй системі, %.sздається, поводиться так само, як %.0s.
  • Якщо ви хочете запустити кілька команд 0000000000000000в якості аргументу, вам потрібно зробити це лише один раз.

glenn jackman вказує, що (де число є додатним цілим числом) буде надруковано рядок нульових чисел (і новий рядок), оскільки зірочка у форматі говорить приймати ширину поля з аргументів. Зокрема, буде надруковано 16 нулів. Але це особливий випадок, який стосується лише .  буде надрукувати та надрукує та повідомлення про помилку. На противагу цьому, інші команди в цій відповіді створюють рядки типу ( або (див. Нижче для ).printf "%0*d\n" number 0printfprintf "%0*d" 16 0 0printf "%0*d" 16 123450000000000012345printf "%0*d" 16 foo0000000000000000123451234512345…foofoofoo…7%7%7%...

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

rep() { printf -- "$1%.0s" $(seq 1 "$2"); printf "\n"; }

Примітки:

  • Використовуйте $(seq 1 "$2")замість того, (1.."$2"}що останні не працюватимуть - дивіться це , це , це та це . Зауважте, що деякі відповіді на ці запитання пропонують використовувати eval, але це, як правило, не рекомендується.
  • Рядок формату ( $1%.0s) повинен містити подвійні лапки (а не одинарні лапки), оскільки він містить параметр ( $1).
  • Це --захист від $1цінностей, починаючи з -.
  • Ви можете отримати подібний захист, використовуючи "%.0s$1"замість "$1%.0s".
  • У будь-якому випадку $1значення, яке містить, %призведе до того, що воно задихнеться.
  • Якщо вам потрібно вміти обробляти $1значення, що містять %, зробіть

    rep() { local i; for ((i=0; i<$2; i++)); do printf '%s' "$1"; done; printf "\n"; }

Крім того, після визначення такої функції ви можете робити такі речі

foo --bar=baz "$(rep 0 16)"

що трохи менше вводити, ніж "$(printf '0%.0s' {1..16})".


По черзі printf "%0*d" 16 0буде надруковано 16 нулів. Зірочка у форматі буде приймати ширину поля з аргументів
glenn jackman
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.