Como substituir um caractere para obter muitas strings no Shell?

Como substituir um caractere para obter muitas strings no Shell?

Posso encontrar muitas perguntas com respostas na outra direção, mas infelizmente não naquela que gostaria que meus substitutos: pretendosubstituir um caractere, como #,em uma corda, como test#asdf, com uma sequência, como{0..10} para obter uma sequência de strings, neste exemplo test0asdf test1asdf test2asdf test3asdf test4asdf test5asdf test6asdf test7asdf test8asdf test9asdf test10asdf.

Eu tentei, de outros:

  • echo '_#.test' | tr # {0..10}(joga uso)
  • echo '_#.test' | sed -r 's/#/{0..10}/g'(retorna _{0..10}.test)
  • echo '_#.test' | sed -r 's/#/'{0..10}'/g'(funciona para o primeiro, depois eu recebo sed: can't read (...) no such file or directory)

Qual é uma abordagem funcional para este problema?

Edite, como não posso comentar ainda: tenho que usar #na string, na qual esse caractere deve ser substituído, como a string passada de outro programa. Eu poderia primeiro substituí-lo por outro caractere.

Responder1

O {0..10} zshoperador (agora também suportado por alguns outros shells, incluindo bash) é apenas outra forma de cshexpansão de chaves no estilo -.

Está expandidopela cascaantes de chamar o comando. O comando não vê esses arquivos {0..10}.

With tr '#' {0..10}(citando que #caso contrário é analisado pelo shell como o início de um comentário), trtermina sendo chamado com ("tr", "#", "0", "1", ..., "10") como argumentos e trnão espera tantos argumentos.

Aqui, você iria querer:

echo '_'{0..10}'.test' 

para echoserem passados ​​"_0.test", "_1.test", ..., "_10.test" como argumentos.

Ou se você quiser que isso #seja traduzido nesse {0..10}operador, transforme-o em código shell para ser avaliado:

eval "$(echo 'echo _#.test' | sed 's/#/{0..10}/')"

onde evalestá sendo passado echo _{0..10}.testcomo argumentos.

(não que eu recomendaria fazer algo assim).

Responder2

Você podedividira string no delimitador, capture o prefixo e o sufixo e use a expansão de chaves para gerar os nomes:

str='test#asdf'
IFS='#' read -r prefix suffix <<<"$str"
names=( "$prefix"{0..10}"$suffix" )
declare -p names
declare -a names='([0]="test0asdf" [1]="test1asdf" [2]="test2asdf" [3]="test3asdf" [4]="test4asdf" [5]="test5asdf" [6]="test6asdf" [7]="test7asdf" [8]="test8asdf" [9]="test9asdf" [10]="test10asdf")'

Responder3

Você tem que usar #? Talvez você possa usar %d?

$ for i in {1..10}; do printf "_%d.test " "$i"; done
_1.test _2.test _3.test _4.test _5.test _6.test _7.test _8.test _9.test _10.test

Responder4

eu faria isso comexpansão de parâmetros:

$ var='test#asdf'
$ for i in {1..10}; do echo "${var/\#/"$i"}"; done
test1asdf
test2asdf
test3asdf
test4asdf
test5asdf
test6asdf
test7asdf
test8asdf
test9asdf
test10asdf

A expansão${parameter/pattern/string}

  • leva a expansão de (no nosso caso, ) e$parameter$var
  • substitui a primeira ocorrência depattern(o escape #/#tem um significado especial no contexto, "substituir no início da string", que queremos evitar) com
  • string( "$i"no nosso caso)

Como alternativa, você pode substituir #por %de usá-lo como string de formato para printf:

printf "${var/\#/%d}\\n" {1..10}

informação relacionada