bash: ¿Cómo usar múltiples manipulaciones de cadenas (expansión de parámetros) en un solo paso?

Aug 15 2020

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:

  1. ¿Es esta la mejor opción?
  2. 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

2 ilkkachu Aug 15 2020 at 20:39

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.