bash: ¿Cómo usar múltiples manipulaciones de cadenas (expansión de parámetros) en un solo paso?
Tengo string=substr1-substr2-substr3.substr4donde las subcadenas son de longitud variable. Quiero extraer substr3desde stringy estoy pensando en hacer que el uso de los ${string##pattern}y las ${string%pattern}expansiones de manipulación de cadenas. Con este enfoque, está claro que necesito ejecutar ${string##*-}y ejecutar ${string%.*}en la expansión resultante, o viceversa. Mis preguntas son:
- ¿Es esta la mejor opción?
- Si es así, ¿cómo ejecuto ambos en un solo paso? Cuando trato de hacer algo como
${string##*-${string%.*}}o${string%.*${string##*-}}simplemente recupero la cadena completa. Me doy cuenta de que siempre puedo hacer la extracción en dos pasos asignando una variable intermedia al resultado del primer paso y luego manipulándolo; pero quiero hacerlo en un solo paso. ¿Cómo lo hago?
TIA!
Respuestas
Dado
string=substr1-substr2-substr3.substr4
${string%.*} es
substr1-substr2-substr3
entonces, ${string##*-${string%.*}}es
${string##*-substr1-substr2-substr3}
lo que significa eliminar desde el principio de string, todo hasta e inclusive -substr1-substr2-substr3. Pero no hay tal subcadena string, ya que no hay un guión delante substr1, por lo que obtienes la cadena original.
Lo que probablemente quieras es
string=substr1-substr2-substr3.substr4
result="${string%.*}" result="${result##*-}"
lo que lleva a resultcontaing substr3.
En Zsh, podría hacerlo en un solo paso:, pero eso no funciona en Bash.result=${${string%.*}##*-}
En Bash, está limitado a usar expansiones en el lado derecho de #o %, y eso no lo ayuda aquí, ya que necesita eliminar partes tanto del inicio como del final de la cadena.
Alternativamente, si $stringno contiene caracteres de nueva línea, puede usar
IFS=.- read -r a b c d <<< "$string"
y leer substr3de c.
En ese caso, dependiendo del shell y el tamaño de la cadena, el contenido de $stringse almacenará en un archivo temporal o se alimentará a través de una tubería que readleerá la primera línea y la dividirá de acuerdo con $IFS.