Repita o caracter n vezes no prompt do zsh

Repita o caracter n vezes no prompt do zsh

Estou trabalhando em um prompt ZSH personalizado e quero repetir um caractere nem uma string (como espaços para preenchimento). Esta string é impressa com print -rP(o -rsinalizador ignora as convenções de escape de eco e o -Psinalizador executa expansões de prompt).

Tenho um código funcionando usando algum tipo de substituição de string, mas não sei como funciona. Por alguma razão, tenho que multiplicar o número de caracteres que desejo imprimir por dois, o que parece um hack.

$ n=3
$ c='a'
$ print -rP "${(l:$n::$c:)}" # why doesn't this work?
ca
$ print -rP "${(l:(( $n * 2 ))::$c:)}" # but this does?
aaa

Então, 1) por que isso funciona quando multiplicado por dois e 2) qual é a sintaxe correta para repetir um caractere dentro de uma string?

Responder1

1) por que isso funciona quando multiplicado por dois,

A expansão "${(l:3::$c:)}"se expande para c$cenquanto "${(l:3*2::$c:)}"se expande para $c$c$c. Se a opção PROMPT_SUBSTestiver definida e esta sequência for usada como parte de uma sequência de prompt, ela será avaliada para expansão de parâmetros, substituição de comandos e expansão aritmética. Então se c=a, então c$cse torna cae $c$c$cse torna aaa.

Teste com XTRACEconjunto:

$ n=3 c=a zsh -o PROMPT_SUBST -xc 'print -rP -- "${(l:n::$c:)}"'
+zsh:1> print -rP -- 'c$c'
ca
$ n=3 c=a zsh -o PROMPT_SUBST -xc 'print -rP -- "${(l:n*2::$c:)}"'
+zsh:1> print -rP -- '$c$c$c'
aaa

e 2) qual é a sintaxe correta para repetir um caractere dentro de uma string?

O lsinalizador de expansão de parâmetro pode ser usado da mesma maneira que você já está usando. No entanto, o psinalizador deve ser usado para permitir $cque o argumento da string seja considerado o valor da variável cantes do preenchimento (obrigado @StéphaneChazelas por apontar isso).

$ n=3 c=a zsh -xc 'print -r -- "${(pl:n::$c:)}"'
+zsh:1> print -r -- aaa
aaa

Observe que esta é a única forma de expansão de parâmetros aceita por esta construção, conforme man zshexpn(na seção sobre Flags de Expansão de Parâmetros):

p   Reconheça as mesmas sequências de escape que os printargumentos de string integrados para qualquer um dos sinalizadores descritos abaixo que seguem este argumento.

Alternativamente, com esta opção os argumentos de string podem estar na forma $varem que o valor da variável é substituído. Observe que este formulário é rigoroso; o argumento string não sofre expansão de parâmetro geral.

Responder2

Usando sua notação original, você pode conseguir o que deseja, usando ppelo menoscomeçodos sinalizadores de parâmetro

 print "${(pl:$n::$c:)}"

Para mais informações e alguns outros exemplos úteis, consulte a seção5.4.6: Ainda mais sinalizadores de parâmetrosemCapítulo 5: Substituiçõesdo guia zsh. Menciona maiúsculas P, mas não p:


Aqui estão alguns outros sinalizadores de parâmetros; Estou repetindo alguns deles. Uma opção muito útil é tinformar o tipo de parâmetro. Isso também apareceu no capítulo 3. O uso mais comum é testar o tipo básico do parâmetro antes de tentar usá-lo:

  if [[ ${(t)myparam} != *assoc* ]]; then
    # $myparam is not an associative array.  Do something about it.
  fi

Outro tipo muito útil é o preenchimento esquerdo ou direito de uma string, até um comprimento especificado e, opcionalmente, com uma string de preenchimento especificada para usar em vez de espaço; você pode até especificar uma string única para ir ao lado da string em questão.

  foo='abcdefghij'
  for (( i = 1; i <= 10; i++ )); do
   goo=${foo[1,$i]}
   print ${(l:10::X::Y:)goo} ${(r:10::X::Y:)goo}
  done

imprime o bastante bonito:

  XXXXXXXXYa aYXXXXXXXX
  XXXXXXXYab abYXXXXXXX
  XXXXXXYabc abcYXXXXXX
  XXXXXYabcd abcdYXXXXX
  XXXXYabcde abcdeYXXXX
  XXXYabcdef abcdefYXXX
  XXYabcdefg abcdefgYXX
  XYabcdefgh abcdefghYX
  Yabcdefghi abcdefghiY
  abcdefghij abcdefghij

Observe que esses dois pontos (que podem ser outros caracteres, como expliquei para os sinalizadores ( s) e ( j)) sempre ocorrem em pares antes e depois do argumento, de modo que, com três argumentos, os dois pontos intermediários são duplicados. Você pode perder parte :Y:e :X:parte e ver o que acontece. As strings de preenchimento não precisam ter caracteres únicos; se eles não couberem um número exato de vezes no espaço de preenchimento, a última repetição será truncada na extremidade mais distante do argumento do parâmetro que está sendo inserido.

Dois parâmetros informam ao shell que você deseja que algo especial seja feito com o valor da substituição do parâmetro. A Pflag ( ) força o valor a ser tratado como um nome de parâmetro, para que você obtenha o efeito de uma substituição dupla:

  % final=string
  % intermediate=final
  % print ${(P)intermediate}
  string

É um pouco como se $intermediatefosse o que em ksh é chamado de a nameref, um parâmetro marcado como referência a outro parâmetro. Zsh pode eventualmente ter isso também; há lugares onde eles são muito mais convenientes do que a (P)bandeira.

Um sinalizador mais poderoso é ( e), que força o valor a ser verificado novamente para todas as formas de substituição de uma única palavra. Por exemplo,

  % foo='$(print $ZSH_VERSION)'
  % print ${(e)foo}
  4.0.2

fez com que o valor de $foofosse reexaminado, momento em que a substituição do comando foi encontrada e executada.

Os sinalizadores restantes são alguns truques simples de formatação especial: ordene os elementos da matriz em ordem lexical normal (caractere) com ( o), ordene na ordem inversa com ( O), faça o mesmo independentemente de maiúsculas e minúsculas com ( oi) ou ( Oi) respectivamente, expanda o prompt %- escapa com ( %) (fácil de lembrar), expande escapes de barra invertida como print faz com p, força todos os caracteres para letras maiúsculas com ( U) ou minúsculas com ( L), coloca o primeiro caractere da string em maiúscula ou cada elemento da matriz com ( C), aparece caracteres especiais como sequências de escape com ( V). Isso deve ser suficiente para continuar.

informação relacionada