¿Cómo reemplazar un carácter para obtener muchas cadenas en Shell?

¿Cómo reemplazar un carácter para obtener muchas cadenas en Shell?

Puedo encontrar muchas preguntas con respuestas en el otro sentido, pero lamentablemente no en el que me gustaría tener mis sustitutos: tengo la intención dereemplazar un carácter, como #,en una cuerda, como test#asdf, con una secuencia, como{0..10} para obtener una secuencia de cadenas, en este ejemplo test0asdf test1asdf test2asdf test3asdf test4asdf test5asdf test6asdf test7asdf test8asdf test9asdf test10asdf.

Intenté, de otros:

  • echo '_#.test' | tr # {0..10}(tira el uso)
  • echo '_#.test' | sed -r 's/#/{0..10}/g'(devoluciones _{0..10}.test)
  • echo '_#.test' | sed -r 's/#/'{0..10}'/g'(funciona para el primero, después lo consigo sed: can't read (...) no such file or directory)

¿Cuál es un enfoque de trabajo para este problema?

Editar, ya que es posible que no comente todavía: tengo que usar #en la cadena, en la que se debe reemplazar este carácter, como la cadena pasada desde otro programa. Sin embargo, primero podría reemplazarlo con otro carácter.

Respuesta1

El {0..10} zshoperador (ahora también compatible con algunos otros shells, incluido bash) es solo otra forma de cshexpansión de llaves estilo -.

esta ampliadopor el caparazónantes de llamar al comando. El comando no los ve {0..10}.

Con tr '#' {0..10}(citando eso #, de lo contrario, el shell lo analiza como el comienzo de un comentario), trtermina siendo llamado con ("tr", "#", "0", "1", ..., "10") como argumentos y trno espera tantas discusiones.

Aquí querrás:

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

para echopasar "_0.test", "_1.test", ..., "_10.test" como argumentos.

O si desea que eso #se traduzca a ese {0..10}operador, transfórmelo en código shell para ser evaluado:

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

donde evalse pasa echo _{0..10}.testcomo argumentos.

(No es que recomendaría hacer algo así).

Respuesta2

Puededividirla cadena en el delimitador, capture el prefijo y el sufijo, luego use la expansión de llaves para generar los nombres:

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")'

Respuesta3

¿Tienes que usar #? ¿Quizás podrías 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

Respuesta4

lo haría conexpansión 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

La expansión${parameter/pattern/string}

  • toma la expansión de (en nuestro caso, ) y$parameter$var
  • reemplaza la primera aparición depattern(el escape #/#tiene un significado especial en el contexto, "reemplazar al principio de la cadena", lo cual queremos evitar) con
  • string( "$i"en nuestro caso)

Alternativamente, puede reemplazar #con %dy usarlo como cadena de formato para printf:

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

información relacionada