Come posso inserire n ripetizioni di una cifra in bash, in modo interattivo


20

Vorrei eseguire il comando

foo --bar=baz <16 zeroes>

Come digitare in modo efficiente i 16 zero *? Se lo tengo premuto Alte 1 6 0lo ripeterò per la prossima volta 160 volte, che non è quello che voglio. In emacs posso usare Alt-[number]o Ctrl-u 1 6 Ctrl-u 0, ma in bash Ctrl-uuccide la riga attualmente in fase di digitazione e lo zero successivo aggiunge solo uno 0 alla riga.

Se lo faccio

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

Quindi historymostra esattamente quanto sopra e non foo --bar=baz 0000000000000000; cioè bash non si comporta come voglio. ( Modifica : punto essendo, voglio inserire un numero di zero senza usare la $(...)sostituzione di comando)

(*) Immagino che una definizione tecnica di "efficientemente" sia "con O (log n) sequenze di tasti", preferibilmente un numero di sequenze di tasti uguale al numero di cifre in 16 (per tutti i valori di 16) più forse una costante; l'esempio di emacs si qualifica efficiente da questa definizione.


1
Sembra che tu voglia bash in qualche modo know what you want to do. In un comando annidato complesso come farebbe a sapere quali parti volevi vedere il risultato dell'esecuzione nella storia rispetto al comando stesso? Che dire delle variabili? In breve bash avrà sempre codela cronologia, non il risultato dell'esecuzione del codice.
Unbeliever,

@meuh, di Altper sé non invia alcun carattere, quindi premere e rilasciare alt non avrà alcun effetto per quanto bashriguarda.
Stéphane Chazelas,

1
@Unbeliever Fai quello che voglio dire e andrà bene
cat

@Unbeliever: vedi la mia modifica, il punto del paragrafo che ha a che fare con questo historyè che vorrei inserire cifre senza usare la sostituzione dei comandi.
Jonas Kölker,

Ogni volta che vuoi che le cose vengano digitate automaticamente per te, AutoKey è una grande utility da usare. Con esso, puoi creare sostituzioni di frasi o completare macro Python che faranno quasi tutto ciò che ti piace quando si digita una frase di trigger o si preme un tasto di scelta rapida. Non l'ho incluso come risposta perché richiede un ambiente desktop GUI e il resto delle risposte no - e sono quindi più generalmente applicabili.
Joe,

Risposte:


25

Provare

eco Alt+1Alt+6Ctrl+V0

Sono 6 i tasti premuti (supponendo almeno una tastiera QWERTY USA / UK) per inserire quei 16 zeri (puoi tenerli Altsia per 1 che per 6).

Puoi anche usare la vimodalità standard ( set -o vi) e digitare:

echo 0 Escx16p

(anche 6 sequenze di tasti).

La emacsmodalità equivalente e che potrebbe essere utilizzata per ripetere più di un singolo carattere ( ) funziona in , ma non in .echo 0Ctrl+WAlt+1Alt+6Ctrl+Yzshbash

Tutti quelli funzioneranno anche con zsh(e da tcshdove proviene). Con zsh, puoi anche usare i flag di espansione delle variabili di padding ed espanderli con Tab:

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

(Ovviamente molte più battiture).

Con bash, puoi anche bashespandere il tuo $(printf '0%.0s' {1..16})con Ctrl+Alt+E. Nota però che espanderà tutto (non i globs) sulla linea.

Per giocare con il minor numero di tasti premuti, potresti associare ad alcuni tasti un widget che si espande <some-number>Xa tempi Xripetuti <some-number>. E avere <some-number>in base 36 per ridurlo ulteriormente.

Con zsh(associato 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

Quindi, per 16 zeri, si digita:

echo g0F8

(3 sequenze di tasti) dove si gtrova 16nella base 36.

Ora possiamo ridurlo ulteriormente a una chiave che inserisce quei 16 zeri, anche se sarebbe un imbroglio. Potremmo legarci F2a due 0s (o due $STRING, 0 per impostazione predefinita), F3a 3 0s, F1F6a 16 0s ... fino a 19 ... le possibilità sono infinite quando è possibile definire widget arbitrari.

Forse dovrei menzionare che se tieni premuto il 0tasto, puoi inserire tutti gli zeri che vuoi con un solo tasto :-)


Grazie per aver fornito più varianti per vie altri!
Mark Stewart,

9

Presumendo che l'emulatore di terminale non manchi la sequenza di tasti (ad es. Per passare da una scheda all'altra) - spiega che funziona xterm - è possibile premere Alt-1 6 Ctrl-V 0. Il control-V è necessario per scomporre il numero e il personaggio da ripetere (se ripetessi una lettera, non ne avresti bisogno).

(Questa è una funzione readline nota come digit-argument, quindi dovresti essere in grado di usare bindper cambiare i tasti modificatori coinvolti)


1
Grazie, incluso il nome della funzione è utile quando le persone come me si imbattono in queste domande. Link correlati per leggere un po 'di più: SO Question and bash manual
admalledd

4

In Emacs, normalmente userei C-qper separare l'argomento prefisso dall'input della cifra.

Bash utilizza Ctrl+vinvece di C-q, per evitare problemi con il controllo del flusso XON / XOFF.

Quindi puoi usare Alt+1 Alt+6 Ctrl+v 0.


3

un'altra opzione è digitare quattro zero e quindi utilizzare il mouse per copiarlo e incollarlo altre tre volte. fai doppio clic per selezionare, fai clic con il pulsante centrale x 3 per incollare.


O golf / imbrogliare ancora un po 'digitando uno zero, selezionare e incollarlo per ottenere 2; seleziona e incolla quello per ottenere 4; seleziona e incolla in 8 e di nuovo per 16. È POWerful :)
Jeff Schaller

sì, ma digitando 4 zero e incollandoli ripetutamente mi sembra il livello ottimale di sforzo contro il payoff. tutta quella copia e incolla in più sembra lavoro.
Cas

3

Giocare con le macro:

Associare il tasto funzione F8per moltiplicare per due l'ultima parola (nello spazio precedente) (codice tasto F8 trovato utilizzando Ctrl-V F8):

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

Ciò potrebbe essere reso permanente inviando lo stesso testo a ~/.inputrc

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

quindi digitare:

eco 0F8F8F8F8

per ottenere 2 ^ 4 volte lo zero. (ancora 5 battute).

o digitare:

libro di ecoF8F8F8

per ottenere 2 ^ 3 parole del libro.

Ancora più veloce:

Moltiplicare per 4:

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

eco 0F8F8

3 tasti premuti.

Moltiplicare per 8 (lo stesso numero del tasto funzione)

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

eco 00F8

Ancora 3 tasti premuti.

Truffare?

Trucchi moltiplicando per 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"'

eco 0F8

Solo 2 tasti premuti. (e ancora un'utile semplice funzione)

^^^^^^^^^^^^^^^^ (base 36? Hah!) :-P

Cheat chiaramente:

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

eco F8

Solo 1 (sì: uno ) battitura.



Modifica dell'associazione per ctrl+U:

Invia questo a ~/.inputrc:

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

Rileggi il ~/.inputrcfile:

ctrl+Xctrl+R

fallo come al solito in emacs (come volevi):

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

7 tasti (dopo la "configurazione").

Leggermente più corto:

Usa il valore predefinito "moltiplica per 4" di "argomento universale" e termina con

 ctrl+V 0 

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

Solo 5 chiavi.

Utilizzo alt+ndell'accesso a (arg: n)

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

Sono 6 chiavi per ottenere i 16 zeri.

Non modificare alcuna scorciatoia da tastiera:

Se nella tua bash hai bash C-u kills the currently-being-typed line.
Questo perché "\C-u":è legato a unix-line-discard.

Ma ciò potrebbe anche aiutare:
quando, ciò che è prima che il cursore venga cancellato, viene anche posizionato nel "kill-ring".

Quindi ctrl+ucancella e ctrl+ystrappa indietro ciò che è stato cancellato.
Su una linea pulita: digita 00cancellalo e tiralo indietro due volte per farlo 0000.
Ripeti per ottenere 00000000(8 zeri), infine digita il comando e torna indietro due volte.

Il primo set (tenere ctrlpremuti 7 tasti ):

00 ctrl+Uctrl+Yctrl+Y ctrl+U 

Il secondo set (5 tasti)

ctrl+Uctrl+Yctrl+Y ctrl+U 

Verranno visualizzati otto zeri nell'anello di cancellazione, quindi digita ciò che desideri:

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

ottenere:

foo --bar=baz 0000000000000000

Dopo aver avuto l'idea, puoi anche digitare ciò di cui hai bisogno, andare all'inizio della riga ( ctrl-Y), fare come sopra (fino a otto zeri) andare alla fine ( ctrl-E) e tirare due volte.

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

Sono 15 tasti (accanto al comando stesso).
Non breve, lo so, ma funziona solo con ciò che era disponibile.

Questo è un po 'più breve:

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

Sono 11 chiavi


Vedi modifica della mia risposta ;-)
Stéphane Chazelas,

@ StéphaneChazelas Usando le macro? Base 36? Solo in zsh? Dai ... vedi la mia modifica :-P
sorontar

Bene sì, la base36 era un po 'lingua nelle guance. Mi piace la tua F<n>duplicazione delle ultime parole <n>.
Stéphane Chazelas,

Nota che non tutti i terminali inviano la stessa sequenza su F8 (anche se la maggior parte di quelli trovati su sistemi GNU / Linux lo fanno ^[[19~). Vedere "$(tput kf8)"per ottenere le informazioni dal database terminfo (o l' $terminfohash in zsh).
Stéphane Chazelas,

@ StéphaneChazelas Sì, è corretto. O semplicemente usactrl-v F8
sorontar l'

2

Come variazione della risposta di cas , digitare

printf '0% .s' {1..16}Enter
e quindi usa il mouse per copiarlo e incollarlo (una volta). Probabilmente, questo è O (log n), ma poiché è (len (str (n)) + 20), potresti considerarlo inefficiente. Ma nota:

  • Sono stato in grado di radere via un personaggio - sul mio sistema, %.ssembra comportarsi come %.0s.
  • Se si desidera eseguire più comandi con 0000000000000000come argomento, è necessario eseguire questa operazione una sola volta.

glenn jackman sottolinea che (dove il numero è un numero intero positivo) stamperà una stringa di zeri numerici (e una nuova riga), poiché l'asterisco nel formato dice di prendere la larghezza del campo dagli argomenti. In particolare, verranno stampati 16 zeri. Ma questo è un caso speciale che gestisce solo .  stamperà e stamperà e un messaggio di errore. Al contrario, gli altri comandi in questa risposta produrranno stringhe come o (e vedi sotto per ).printf "%0*d\n" number 0printfprintf "%0*d" 16 0 0printf "%0*d" 16 123450000000000012345printf "%0*d" 16 foo0000000000000000123451234512345…foofoofoo…7%7%7%...

Se lo farai su base frequente, puoi semplificarlo definendo una funzione shell:

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

Gli appunti:

  • Usa $(seq 1 "$2")invece che (1.."$2"}perché quest'ultimo non funzionerà - vedi questo , questo , questo e questo . Nota che alcune delle risposte a queste domande suggeriscono di usareeval , ma questo non è generalmente raccomandato.
  • La stringa di formato ( $1%.0s) deve essere racchiusa tra virgolette (anziché tra virgolette singole) perché contiene un parametro ( $1).
  • È --proteggere dai $1valori che iniziano con -.
  • È possibile ottenere una protezione simile utilizzando "%.0s$1"invece di "$1%.0s".
  • Ad ogni modo, un $1valore contenente lo %farà soffocare.
  • Se devi essere in grado di gestire i $1valori contenenti %, fallo

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

Inoltre, una volta definita una tale funzione, puoi fare cose del genere

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

che è leggermente meno digitando di "$(printf '0%.0s' {1..16})".


In alternativa printf "%0*d" 16 0stamperà 16 zeri. L'asterisco nel formato prenderà la larghezza del campo dagli argomenti
glenn jackman,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.