bash: ¿Cómo usar múltiples manipulaciones de cadenas (expansión de parámetros) en un solo paso?
Tengo string=substr1-substr2-substr3.substr4
donde las subcadenas son de longitud variable. Quiero extraer substr3
desde string
y 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 result
containg 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 $string
no contiene caracteres de nueva línea, puede usar
IFS=.- read -r a b c d <<< "$string"
y leer substr3
de c
.
En ese caso, dependiendo del shell y el tamaño de la cadena, el contenido de $string
se almacenará en un archivo temporal o se alimentará a través de una tubería que read
leerá la primera línea y la dividirá de acuerdo con $IFS
.