Como faço para inserir n repetições de um dígito no bash, interativamente

19

Eu gostaria de executar o comando

foo --bar=baz <16 zeroes>

Como eu digito os 16 zeros de forma eficiente *? Se eu segurar Alt e pressionar 1 6 0 ele irá repetir a próxima coisa 160 vezes, o que não é o que Eu quero. No emacs eu posso usar Alt- [número] ou Ctrl-u 1 6 Ctrl- u 0 , mas no bash Ctrl-u mata a linha que está sendo digitada no momento e o próximo zero apenas adiciona um 0 à linha.

Se eu fizer

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

Em seguida, history mostra exatamente o acima, e não foo --bar=baz 0000000000000000 ; ou seja, o bash não se comporta da maneira que eu quero. ( Editar : point sendo, eu quero inserir um número de zeros sem usar a substituição do comando $(...) )

(*) Eu acho que uma definição técnica de "eficientemente" é "com O (log n) pressionamentos de teclas", preferencialmente um número de teclas igual ao número de dígitos em 16 (para todos os valores de 16) mais talvez uma constante ; o exemplo do emacs qualifica-se como eficiente por esta definição.

    
por Jonas Kölker 10.10.2016 / 15:40

6 respostas

25

Tente

echo Alt+1Alt+6Ctrl+V0

São 6 toques de teclas (supondo pelo menos um teclado QWERTY EUA / Reino Unido) para inserir esses 16 zeros (você pode segurar Alt para 1 e 6).

Você também pode usar o modo vi padrão ( set -o vi ) e digitar:

echo 0Escx16p

(também 6 toques de tecla).

O equivalente a emacs e que pode ser usado para repetir mais de um caractere ( echo 0Ctrl+WAlt+1Alt+6Ctrl+Y ) funciona em zsh , mas não em bash .

Todos esses também funcionarão com zsh (e tcsh de onde isso vem). Com zsh , você também pode usar sinalizadores de expansão de variável de preenchimento e expandi-los com a aba :

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

(muito mais pressionamentos de teclas, obviamente).

Com bash , você também pode ter bash expandindo seu $(printf '0%.0s' {1..16}) com Ctrl + Alt + E . Note, entretanto, que isso expandirá tudo (não os globs) na linha.

Para jogar o jogo com o menor número de toques de tecla, você pode vincular a um widget de chave que expande <some-number>X para X repetido <some-number> times. E tem <some-number> na base 36 para reduzir ainda mais.

Com zsh (ligado 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

Então, por 16 zeros, você digita:

echo g0F8

(3 pressionamentos de tecla) em que g é 16 na base 36.

Agora podemos reduzi-lo ainda mais a uma chave que insere esses 16 zeros, embora isso seja uma fraude. Nós poderíamos ligar F2 a dois 0 s (ou dois $STRING , 0 por padrão), F3 a 3 0 s, F1 F6 para 16 0 s ... até 19 ... as possibilidades são infinitas quando você pode definir widgets arbitrários.

Talvez eu deva mencionar que se você pressionar e segurar a tecla 0 , você pode inserir quantos zeros quiser com apenas um pressionamento de tecla: -)

    
por 10.10.2016 / 16:03
9

Presumindo que seu emulador de terminal não consuma o pressionamento de tecla (por exemplo, para alternar as guias) - trabalhos simples do xterm - você pode pressionar Alt-1 6 Ctrl -V 0 . O controle-V é necessário para dividir o número e o caractere a ser repetido (se você estivesse repetindo uma carta, não precisaria).

(Este é um recurso readline conhecido como digit-argument , então você deve ser capaz de usar bind para alterar as teclas modificadoras envolvidas)

    
por 10.10.2016 / 16:03
4

No Emacs, normalmente usaria C-q para separar o argumento do prefixo da entrada de dígitos.

O Bash usa Ctrl + v em vez de C-q , para evitar problemas com o controle de fluxo XON / XOFF.

Então você pode usar Alt + 1 Alt + 6 Ctrl + v 0 .

    
por 10.10.2016 / 17:45
3

outra opção é digitar quatro zeros e depois usar o mouse para copiá-lo e colá-lo mais três vezes. clique duas vezes para selecionar, clique com o botão do meio x 3 para colar.

    
por 10.10.2016 / 16:06
3

Jogando com macros:

Ligue a tecla de função F8 para multiplicar por dois a última palavra (até o espaço anterior) (código chave F8 encontrado usando Ctrl-V F8 ):

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

Isso pode se tornar permanente enviando o mesmo texto para ~/.inputrc

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

digite:

echo 0F8F8F8F8

para obter 2 ^ 4 vezes o zero. (ainda 5 pressionamentos de tecla).

ou digite:

echo bookF8F8F8

para obter 2 ^ 3 palavras de livro.

Ainda mais rápido:

Multiplique por 4:

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

echo 0F8F8

3 pressionamentos de teclas.

Multiplique por 8 (o mesmo número da tecla de função)

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

echo 00F8

Ainda 3 pressionamentos de tecla.

Cheat?

Fraude 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

Apenas 2 pressionamentos de tecla. (e ainda uma função simples útil)

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

Claramente trapaceando:

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

echo F8

Apenas 1 (sim: um ) pressionamento de tecla.

Alterando a ligação para ctrl + U :

Envie para ~/.inputrc :

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

Releia o arquivo ~/.inputrc :

ctrl+Xctrl+R

faça como é habitual no emacs (como você queria):

foo --bar=baz ctrl+U 16 ctrl+U 0

7 teclas (após a "configuração").

Ligeiramente mais curto:

Use o padrão "multiplique por 4" de "argumento universal" e termine com

 ctrl+V 0 

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

Apenas 5 chaves.

Usando o acesso a alt + n para (arg: n)

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

São 6 chaves para obter os 16 zeros.

Não está a alterar nenhum atalho de teclado:

Se no seu bash você tem bash C-u kills the currently-being-typed line .
Isso porque "\C-u": está ligado a unix-line-discard .

Mas isso também pode ajudar:
Quando, o que está antes do cursor ser apagado, ele também é colocado no "kill-ring".

Então, ctrl+u apaga e ctrl+y retorna o que foi apagado.
Em uma linha limpa: Digite 00 apague e arranque duas vezes para torná-lo 0000 .
Repita para obter 00000000 (8 zeros), finalmente digite o comando e retorne duas vezes.

O primeiro conjunto (7 chaves mantêm ctrl pressionado):

00 ctrl+Uctrl+Yctrl+Y ctrl+U 

O segundo conjunto (5 chaves)

ctrl+Uctrl+Yctrl+Y ctrl+U 

Isso produzirá oito zeros no anel de apagamento e, em seguida, digitará o que você deseja:

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

para obter:

foo --bar=baz 0000000000000000

Depois de obter a idéia, você também pode, digitar o que você precisa, ir para o início da linha ( ctrl-Y ), fazer como acima (até oito zeros) ir para o fim ( ctrl-E ) e puxe duas vezes.

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

São 15 chaves (ao lado do comando em si).
Não curto, eu sei, mas isso está funcionando apenas com o que estava disponível.

Isso é um pouco mais curto:

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

São 11 chaves

    
por 11.10.2016 / 09:18
1

Como uma variação da resposta do cas , tipo

printf '0%.s' {1..16}Enter
e depois use o mouse para copiá-lo e colá-lo (uma vez). Indiscutivelmente, este é O (log n), mas como é (len (str (n)) + 20), você pode considerá-lo ineficiente. Mas nota:
  • Eu consegui eliminar um personagem - no meu sistema, %.s parece se comportar da mesma forma que %.0s .
  • Se você quiser executar vários comandos com 0000000000000000 como argumento, você precisa fazer isso apenas uma vez.

glenn jackman aponta que %código% (onde número é um inteiro positivo) irá imprimir uma seqüência de números número (e uma nova linha), como o asterisco no formato informa printf "%0*d\n" number 0 para obter a largura do campo dos argumentos. Especificamente, printf imprimirá 16 zeros. Mas este é um caso especial que lida com somente printf "%0*d" 16 0 . 0 imprimirá printf "%0*d" 16 12345 , e 0000000000012345 imprimirá printf "%0*d" 16 foo e uma mensagem de erro. Por outro lado, os outros comandos nesta resposta produzirá sequências como 0000000000000000 ou 123451234512345… (e veja abaixo para foofoofoo… ).

Se você fizer isso com frequência, você pode simplificá-lo definindo uma função de shell:

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

Notas:

  • Use 7%7%7%... em vez de $(seq 1 "$2") porque o último não funcionará - veja as variáveis , this , isso , e isso . Observe que algumas das respostas para essas perguntas sugerem usar (1.."$2"} , mas isso geralmente não é recomendado.
  • A string de formato ( eval ) deve estar entre aspas duplas (em vez de aspas simples) porque contém um parâmetro ( $1%.0s ).
  • O $1 é para proteger contra valores de -- , começando com $1 .
  • Você pode obter proteção semelhante usando - em vez de "%.0s$1" .
  • De qualquer forma, um valor de "$1%.0s" contendo $1 fará com que ele afogue.
  • Se você precisar manipular valores % contendo $1 , faça

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

Além disso, depois de definir essa função, você pode fazer coisas como

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

que é um pouco menos digitação do que % .

    
por 10.10.2016 / 22:51