Usando uma variável dentro de uma seqüência de comandos no bash para complementar uma string existente - erro de sintaxe ou design defeituoso?

3

Estou usando a seguinte sequência de comandos no meu arquivo .bashrc para alterar a aparência do meu terminal linux. Ele preenche a tela linha por linha com um padrão feito de caracteres. Não há abstração, os caracteres são de um conjunto dentro do próprio comando:

for i in $(seq 1 $(expr $(tput lines))); do echo -en '\E[0;32m'$(tr -dc '",.o;:~' < /dev/urandom | head -c $(tput cols)); done; tput cup 1
                                                                       -->the set

A ideia principal é ler 80 cols (bytes) de alguns caracteres aleatórios do conjunto e imprimir esse número * de linhas. Agora, executei o seguinte script de contribuição para explorar a adição de novos caracteres ao conjunto. Para manter a compatibilidade com o terminal Linux que estou usando, executei isso fora do X etc, com o seguinte resultado:

Gostariadeusaroscaracteresdisponíveisnasequênciaacima.Entãopegueimuitosdelesefizoseguinte,porexemplocom◘:

echo-n◘|hexdump000000097e200980000003sotheUTF-8sequenceis\xE2\x97\x98IbuildallthesequencesIneed:\xE2\x95\x99,\xE2\x95\x9atof,\xE2\x96\x90to93

Então,simplesmenteadicionoaomeuarquivo.bashrcA=$(echo-e'\xE2\x97\x98')eB=$(echo-e',.o;:~')emodificominhasequênciadecomandoassim(ouseja,echo$A$B):

foriin$(seq1$(expr$(tputlines)));doecho-en'\E[0;32m'$(tr-dc$(echo$A$B)</dev/urandom|head-c$(tputcols));done;tputcup1

Seeuecho$Aou$Bnoprompt,eleimprimeo(s)caractere(s).Masquandoasequênciaéchamadaem.bashrc,issogeralmentenãofunciona.Emumatelainteira◘aparecede3a5vezesototal,juntamentecommuitoscaracteresdeespaçoreservado,oquesignificaqueasaídanãoésuportadapelotermo.Osoutrospersonagensdosetestãolá.Deinteresseéqueseeumantivesseasintaxeoriginalsemnenhumavariável$Besimplesmentetentasseadicionar$Aaoset,ietr-dc'",.o'$A';:~' , eu teria exatamente o mesmo tipo de saída, sugerindo que é algo diferente da sintaxe - por causa de / dev / urandom. Outras variações na sintaxe usando citações introduzem mais eco não relacionado.

Como uma nota secundária, no xterm, o resultado é semelhante com diferentes caracteres de espaço reservado, e alguns ☗ e ◗.

Existe uma maneira de trazer a variável no conjunto dessa forma ou isso precisa ser redesenhado do zero para dar conta deste caso?

    
por Community 23.12.2013 / 10:25

1 resposta

0

Esta é uma solução não universal que atinge o resultado pretendido sem explorar a diferença entre tr e a da heirloom toolchest ou redesenhar o que tenho no momento. Como tal, é falho mas pragmático. Como colaborador aludido em relação a tr , há uma restrição para o uso deste comando:

Currently tr fully supports only single-byte characters. Eventually it will support multibyte characters; when it does, the -C option will cause it to complement the set of characters, whereas -c will cause it to complement the set of values. This distinction will matter only when some values are not characters, and this is possible only in locales using multibyte encodings when the input contains encoding errors.

Então, na verdade, somente os caracteres de 8 bits de 1 byte (não-Unicode), como os do meu conjunto inicial, são suportados pela minha sequência. Eu também tenho uma restrição que estou processando uma tela de caracteres e não quero mais, então a idéia de adicionar alguma outra aleatoriedade para os novos caracteres foi menos atraente, ou seja, como controlar caracteres totais escritos. Então eu decidi postar o processo de saída. O escopo de caracteres disponíveis para ser usado como um padrão será menor que o total de caracteres de 1 byte disponíveis para que eu possa usar aqueles que eu nunca pretendi usar em primeiro lugar e redirecioná-los como "variáveis" como esta:

Z1=$(echo -en '\xe2\x97\x98')  \ Z1 to Z9 will be used to
Z2=$(echo -en '\xe2\x95\x9a')  \ bring in our non unicode
Z3=$(echo -en '\xe2\x95\x9c')  \ chars
Z4=$(echo -en '\xe2\x95\x9d')
Z5=$(echo -en '\xe2\x95\x9e')
Z6=$(echo -en '\xe2\x95\x9f')
Z7=$(echo -en '\xe2\x96\x91')
Z8=$(echo -en '\xe2\x96\x92')
Z9=$(echo -en '\xe2\x96\x93')
Z11="$(tr -dc '123456789a' < /dev/urandom | head -c 1)"  \Z11 to Z13 used to
Z12="$(tr -dc '123456789a' < /dev/urandom | head -c 1)"  \reintroduce the chars
Z13="$(tr -dc '123456789a' < /dev/urandom | head -c 1)"  \used as variables

tput setf 6
tput setaf 6

echo -en $(tr -dc '",.o;:~123456789a' < /dev/urandom | head -c $(echo -en "$[$(tput cols) * $(tput lines)]") | sed -e "s/1/$Z1/g" -e "s/2/$Z2/g" -e "s/3/$Z3/g" -e "s/4/$Z4/g" -e "s/5/$Z5/g" -e "s/6/$Z6/g" -e "s/7/$Z7/g" -e "s/8/$Z8/g" -e "s/9/$Z9/g" -e "0,/a/s//$Z11/" -e "0,/a/s//$Z12/" -e "s/a/$Z13/g"); tput cup 1
                   ^set  ^^vars    ^                                                                              "variables" ouput are replaced with intended char>___________________________________________________________________________________________^...then vars themselves reintroduced here as chars, one 'a' at a time(only 3 shown here, last one is global)
                                  |__________________________________________________________________________________|

A sequência atualizada é ligeiramente diferente do que no Q e é simplesmente renderizada em uma varredura limpa, em vez de linha por linha. Ele usa sed e sua capacidade de aceitar muitos comandos para aplicar ao fluxo com -e . Os números de 1 a 9 e a letra "a" são randomizados para o padrão de página inteira. O padrão de saída é então filtrado com sed e 1 a 9 (se presentes no fluxo aleatório) são todos convertidos em nossos caracteres não unicode pretendidos - somente a is permanece. Esses "a" são então processados e usados para reintroduzir os caracteres 1 a 9 e a no padrão usando as variáveis Z11 a Z13 (gerador aleatório com cabeçalho de 1 byte que usa 1-9 e "a" como um conjunto agora que não precisamos mais deles). Cada instância de a poderia ser aleatoriamente individualmente (ver exemplo de padrão abaixo) ou deixada como está (outro caractere que "a" pode ser escolhido, é claro, um que poderíamos gostar de ver no padrão final). Essa prova de conceito está incompleta, já que você precisaria interceptar todos os caracteres a neste exemplo e transformá-los em algo realmente aleatório. Mas isso funciona. Isso é apenas para mostrar que esses chars (e eu selecionaria na prática chars que não quero usar no padrão para que não haja necessidade de reintroduzi-los assim em primeiro lugar) possam ser reintroduzidos. O obstáculo tr foi "evitado".

Podemosveroqueaconteceucomoa-oprimeirofoiconvertidopara8eosegundopara1,enquantoorestantefoiconvertidopara4s(sedglobal).1,4e8foramtodososcaracteresusadosparatrazernossoscaracteresespeciais,eagoraelespodemserusadostambémsenecessário.Semdúvida,existeumasoluçãoelegante,masestanãoéumadelas.Tudoissoégeradoemumpiscardeolhos.

Aquiestáumaversãosimplificadaformatadacomoumscriptqueusaosdígitos1a9paranossopadrãosem"resgatá-los", como explicado acima:

#!/bin/bash

## spptr_dfp.sh - Display a chosen pattern of chars using tr, while using sed "post processors" to deal with
## multibyte chars that tr can't stomach. Rely on single chars not used for the pattern to bring in the
## multibyte ones later on in the pipeline.

## Z1 to Z9 will be used as primitives variables
## to bring in our non unicode chars
Z1=$(echo -en '\xe2\x97\x98')
Z2=$(echo -en '\xe2\x95\x9a')
Z3=$(echo -en '\xe2\x95\x9c')  
Z4=$(echo -en '\xe2\x95\x9d')
Z5=$(echo -en '\xe2\x95\x9e')
Z6=$(echo -en '\xe2\x95\x9f')
Z7=$(echo -en '\xe2\x96\x91')
Z8=$(echo -en '\xe2\x96\x92')
Z9=$(echo -en '\xe2\x96\x93')

## the color we want
tput setf 6
tput setaf 6

## the main event, generated for cols*lines
## the pattern is made out of ",.o;:~
## the single chars used as vars are 123456789
## after tr outputs, sed converts any of the single chars to our multibyte chars
echo -en $(tr -dc '",.o;:~123456789' < /dev/urandom | head -c $(echo -en "$[$(tput cols) * $(tput lines)]") | sed -e "s/1/$Z1/g" -e "s/2/$Z2/g" -e "s/3/$Z3/g" -e "s/4/$Z4/g" -e "s/5/$Z5/g" -e "s/6/$Z6/g" -e "s/7/$Z7/g" -e "s/8/$Z8/g" -e "s/9/$Z9/g")

tput cup 1

exit
    
por 24.12.2013 / 10:43

Tags