¿Cómo ingreso n repeticiones de un dígito en bash, interactivamente


20

Me gustaría ejecutar el comando

foo --bar=baz <16 zeroes>

¿Cómo escribo los 16 ceros de manera eficiente *? Si lo sostengo Alty lo presiono 1 6 0, se repetirá lo siguiente 160 veces, que no es lo que quiero. En emacs puedo usar Alt-[number]o Ctrl-u 1 6 Ctrl-u 0, pero en bash Ctrl-umata la línea que se está escribiendo actualmente y el siguiente cero simplemente agrega un 0 a la línea.

Si lo hago

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

Luego historymuestra exactamente lo anterior, y no foo --bar=baz 0000000000000000; es decir, bash no se comporta como yo quiero. ( Editar : punto, quiero ingresar un cierto número de ceros sin usar la $(...)sustitución de comandos)

(*) Supongo que una definición técnica de "eficientemente" es "con O (log n) pulsaciones de teclas", preferiblemente una cantidad de pulsaciones de tecla igual al número de dígitos en 16 (para todos los valores de 16) más quizás una constante; El ejemplo de emacs califica como eficiente por esta definición.


1
Parece que quieres bash de alguna manera know what you want to do. En un comando anidado complejo, ¿cómo sabrá bash qué partes desea ver el resultado de la ejecución en el historial en lugar del comando en sí? ¿Qué pasa con las variables? En resumen, bash siempre va a tener codeel historial, no el resultado de ejecutar el código.
creyente

@meuh, Altpor sí solo no envía ningún personaje, por lo que presionar y soltar alt no tendrá ningún efecto en lo que bashrespecta.
Stéphane Chazelas

1
@Unbeliever Haz lo que quiero decir y estará bien
gato

@Increíble: vea mi edición: el punto del párrafo que tiene que ver historyes que me gustaría ingresar dígitos sin usar la sustitución de comandos.
Jonas Kölker

Siempre que desee que las cosas se escriban automáticamente, AutoKey es una gran utilidad para usar. Con él, puede crear sustituciones de frases o completar macros de Python que harán casi cualquier cosa que desee cuando se escribe una frase de activación o se presiona una tecla de acceso rápido. No incluí esto como respuesta porque requiere un entorno de escritorio GUI y el resto de las respuestas no lo hacen, y por lo tanto son más generalmente aplicables.
Joe

Respuestas:


25

Tratar

echo Alt+1Alt+6Ctrl+V0

Son 6 pulsaciones de teclas (suponiendo un teclado QWERTY de EE. UU. / Reino Unido al menos) para insertar esos 16 ceros (puede mantener presionados Alttanto para 1 como para 6).

También puede usar el vimodo estándar ( set -o vi) y escribir:

echo 0 Escx16p

(también 6 pulsaciones de teclas).

El emacsmodo equivalente y que podría usarse para repetir más de un solo carácter ( ) funciona , pero no en .echo 0Ctrl+WAlt+1Alt+6Ctrl+Yzshbash

Todos ellos también funcionarán con zsh(y de tcshdónde viene eso). Con zsh, también puede usar indicadores de expansión variable de relleno y expandirlos con Tab:

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

(Muchas más pulsaciones de teclas, obviamente).

Con bash, también puede bashexpandir su $(printf '0%.0s' {1..16})con Ctrl+Alt+E. Sin embargo, tenga en cuenta que expandirá todo (no los globos) en la línea.

Para jugar el menor número de pulsaciones de teclas, puede vincular a alguna tecla un widget que se expande <some-number>Xa tiempos Xrepetidos <some-number>. Y tener <some-number>en la base 36 para reducirlo aún más.

Con zsh(obligado a 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

Luego, para 16 ceros, escribe:

echo g0F8

(3 pulsaciones de teclas) donde gestá 16en la base 36.

Ahora podemos reducirlo aún más a una clave que inserte esos 16 ceros, aunque eso sería trampa. Podríamos vincular F2a dos 0s (o dos $STRING, 0 por defecto), F3a 3 0s, F1F6a 16 0s ... hasta 19 ... las posibilidades son infinitas cuando puede definir widgets arbitrarios.

Tal vez debería mencionar que si mantiene presionada la 0tecla, puede insertar tantos ceros como desee con solo presionar una tecla :-)


¡Gracias por proporcionar múltiples variaciones para viy otros!
Mark Stewart

9

Suponiendo que su emulador de terminal no se coma la pulsación de tecla (p. Ej., Para cambiar de pestaña), simplemente funciona xterm, puede presionar Alt-1 6 Ctrl-V 0. El control-V es necesario para dividir el número y el carácter para repetir (si repitiera una letra, no la necesitaría).

(Esta es una característica de línea de lectura conocida como digit-argument, por lo que debería poder usarla bindpara cambiar las teclas modificadoras involucradas)


1
Gracias, incluir el nombre de la función es útil cuando personas como yo tropiezan con estas preguntas. Enlaces relacionados para leer un poco más: SO Pregunta y manual de bash
agregado el

4

En Emacs, normalmente lo usaría C-qpara separar el argumento del prefijo de la entrada de dígitos.

Bash utiliza en Ctrl+vlugar de C-q, para evitar problemas con el control de flujo XON / XOFF.

Entonces puedes usar Alt+1 Alt+6 Ctrl+v 0.


3

Otra opción es escribir cuatro ceros y luego usar el mouse para copiar y pegar tres veces más. haga doble clic para seleccionar, haga clic en el medio x 3 para pegar.


O juegue al golf / haga trampa un poco más escribiendo un cero, seleccione y pegue eso para obtener 2; seleccione y pegue eso para obtener 4; seleccione y pegue a 8, y nuevamente para 16. Es POWerful :)
Jeff Schaller

sí, pero escribir 4 ceros y pegarlos repetidamente me parece el nivel óptimo de esfuerzo vs beneficio. todo ese copiado y pegado extra parece trabajo.
cas

3

Jugando con macros:

Vincula la tecla de función F8para multiplicar por dos la última palabra (hasta el espacio anterior) (código de tecla F8 encontrado usando Ctrl-V F8):

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

Eso podría hacerse permanente enviando el mismo texto a ~/.inputrc

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

luego escriba:

echo 0F8F8F8F8

para obtener 2 ^ 4 veces el cero. (Todavía 5 pulsaciones de teclas).

o escriba:

libro de ecoF8F8F8

para obtener 2 ^ 3 palabras del libro.

Aún más rápido:

Multiplicar por 4:

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

echo 0F8F8

3 teclas presionadas.

Multiplique por 8 (el mismo número que la tecla de función)

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

echo 00F8

Todavía 3 pulsaciones de teclas.

¿Engañar?

Haz trampa multiplicando por 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"'

echo 0F8

Solo 2 pulsaciones de teclas. (y sigue siendo una función simple útil)

^^^^^^^^^^^^^^^^ (base 36? ¡Ja!) :-P

Hacer trampa claramente:

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

eco F8

Solo 1 (sí: una ) pulsación de tecla.



Cambiar el enlace para ctrl+U:

Enviar esto a ~/.inputrc:

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

Vuelva a leer el ~/.inputrcarchivo:

ctrl+Xctrl+R

hazlo como es habitual en emacs (como quisieras):

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

7 teclas (después de la "configuración").

Ligeramente más corto:

Utilice el valor predeterminado "multiplicar por 4" de "argumento universal" y terminar

 ctrl+V 0 0 

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

Solo 5 llaves.

Usando el alt+nacceso a (arg: n)

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

Eso son 6 claves para obtener los 16 ceros.

No cambiar ningún atajo de teclado:

Si en tu fiesta tienes bash C-u kills the currently-being-typed line.
Eso es porque "\C-u":está unido a unix-line-discard.

Pero eso también podría ayudar:
cuando, lo que está antes de que se borre el cursor, también se coloca en el "anillo de la muerte".

Entonces ctrl+uborra y ctrl+yretira lo que se borró.
En una línea limpia: escriba 00borrarlo y tirar de él dos veces para hacerlo 0000.
Repita para obtener 00000000(8 ceros), finalmente escriba el comando y tire dos veces hacia atrás.

El primer conjunto (7 teclas ctrlpresionadas):

00 ctrl+Uctrl+Yctrl+Y ctrl+U 

El segundo conjunto (5 teclas)

ctrl+Uctrl+Yctrl+Y ctrl+U 

Obtendrá ocho ceros en el anillo de borrado, luego escriba lo que desee:

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

Llegar:

foo --bar=baz 0000000000000000

Una vez que tenga la idea, también puede escribir lo que necesita, ir al comienzo de la línea ( ctrl-Y), hacer lo anterior (hasta ocho ceros) ir al final ( ctrl-E) y tirar dos veces.

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

Son 15 teclas (al lado del comando en sí).
No es breve, lo sé, pero eso solo funciona con lo que estaba disponible.

Esto es un poco más corto:

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

Eso son 11 llaves


Ver edición de mi respuesta ;-)
Stéphane Chazelas

@ StéphaneChazelas ¿Usa macros? Base 36? Sólo en zsh? Vamos ... mira mi edición
:-P

Bueno, sí, la base36 era un poco lengua en la mejilla. Me gusta que F<n>dupliques la última palabra <n>veces.
Stéphane Chazelas

Tenga en cuenta que no todos los terminales envían la misma secuencia en F8 (aunque la mayoría de los que se encuentran en los sistemas GNU / Linux sí envían ^[[19~). Consulte "$(tput kf8)"para obtener la información de la base de datos terminfo (o el $terminfohash in zsh).
Stéphane Chazelas

@ StéphaneChazelas Sí, eso es correcto. O simplemente usectrl-v F8
sorontar

2

Como una variación de la respuesta cas , escriba

printf '0% .s' {1..16}Enter
y luego use el mouse para copiarlo y pegarlo (una vez). Podría decirse que esto es O (log n), pero dado que es (len (str (n)) + 20), puede considerarlo ineficiente. Pero nota:

  • Pude depilar un personaje: en mi sistema, %.sparece comportarse de la misma manera %.0s.
  • Si desea ejecutar varios comandos con 0000000000000000un argumento, debe hacerlo solo una vez.

Glenn Jackman señala que (donde el número es un entero positivo) imprimirá una cadena de ceros numéricos (y una nueva línea), ya que el asterisco en el formato indica que tome el ancho del campo de los argumentos. Específicamente, imprimirá 16 ceros. Pero este es un caso especial que solo se maneja .  se imprimirá e imprimirá un mensaje de error. Por el contrario, los otros comandos en esta respuesta producirán cadenas como o (y ver más abajo para ).printf "%0*d\n" number 0printfprintf "%0*d" 16 0 0printf "%0*d" 16 123450000000000012345printf "%0*d" 16 foo0000000000000000123451234512345…foofoofoo…7%7%7%...

Si va a hacer esto con frecuencia, puede simplificarlo definiendo una función de shell:

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

Notas:

  • Use en $(seq 1 "$2")lugar de (1.."$2"}porque este último no funcionará: vea esto , esto , esto y esto . Tenga en cuenta que algunas de las respuestas a esas preguntas sugieren usar eval, pero esto generalmente no se recomienda.
  • La cadena de formato ( $1%.0s) debe estar entre comillas dobles (en lugar de comillas simples) porque contiene un parámetro ( $1).
  • El --es proteger contra $1valores que comienzan con -.
  • Puede obtener una protección similar al usar en "%.0s$1"lugar de "$1%.0s".
  • De cualquier manera, un $1valor que contenga %hará que se ahogue.
  • Si necesita poder manejar $1valores que contienen %, haga

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

Además, una vez que haya definido dicha función, puede hacer cosas como

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

que es un poco menos escribiendo que "$(printf '0%.0s' {1..16})".


Alternativamente printf "%0*d" 16 0imprimirá 16 ceros. El asterisco en el formato tomará el ancho del campo de los argumentos
Glenn Jackman
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.