Eliminar un prefijo / sufijo fijo de una cadena en Bash

En mi script bash tengo una cadena y su prefijo / sufijo. Necesito eliminar el prefijo / sufijo de la cadena original.

Por ejemplo, digamos que tengo los siguientes valores:

 string="hello-world" prefix="hell" suffix="ld" 

¿Cómo puedo obtener el siguiente resultado?

 result="o-wor" 

 $ foo=${string#"$prefix"} $ foo=${foo%"$suffix"} $ echo "${foo}" o-wor 

Usando sed:

 $ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//" o-wor 

Dentro del comando sed, el carácter ^ coincide con el texto que comienza con $prefix , y el $ final coincide con el texto que termina con $suffix .

Adrian Frühwirth hace algunos buenos comentarios en los comentarios a continuación, pero sed para este propósito puede ser muy útil. El hecho de que los contenidos de $ prefix y $ sufijo sean interpretados por sed puede ser bueno o malo, siempre y cuando prestes atención, deberías estar bien. La belleza es que puedes hacer algo como esto:

 $ prefix='^.*ll' $ suffix='ld$' $ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//" o-wor 

que puede ser lo que quieres, y es más elegante y más potente que la sustitución de variable bash. Si recuerdas que con gran poder viene una gran responsabilidad (como dice Spiderman), deberías estar bien.

Puede encontrar una introducción rápida a sed en http://evc-cit.info/cit052/sed_tutorial.html

Una nota sobre el shell y su uso de cadenas:

Para el ejemplo particular dado, lo siguiente también funcionaría:

 $ echo $string | sed -es/^$prefix// -es/$suffix$// 

… pero solo porque:

  1. echo no importa cuántas cadenas hay en su lista de argumentos, y
  2. No hay espacios en $ prefijo y $ sufijo

En general, es una buena práctica citar una cadena en la línea de comando porque incluso si contiene espacios, se presentará al comando como un único argumento. Citamos $ prefijo y $ sufijo por la misma razón: cada comando de edición para sed se pasará como una cadena. Usamos comillas dobles porque permiten la interpolación variable; si hubiésemos usado comillas simples, el comando sed habría obtenido un $prefix $suffix y $suffix que ciertamente no es lo que queríamos.

Observe, también, mi uso de comillas simples al establecer las variables prefix y suffix . Ciertamente, no queremos que se interprete nada en las cuerdas, por lo que solo las citemos para que no tenga lugar ninguna interpolación. Nuevamente, puede que no sea necesario en este ejemplo, pero es un hábito muy bueno para entrar.

Yo uso grep para eliminar prefijos de las rutas (que no son manejadas bien por sed ):

 echo "$input" | grep -oP "^$prefix\K.*" 

\K elimina del emparejamiento a todos los personajes anteriores.

¿Conoces la longitud de tu prefijo y sufijo? En tu caso:

 result=$(echo $string | cut -c5- | rev | cut -c3- | rev) 

O más general:

 result=$(echo $string | cut -c$((${#prefix}+1))- | rev | cut -c$((${#suffix}+1))- | rev) 

¡Pero la solución de Adrian Frühwirth es genial! ¡No sabía sobre eso!

Solución pequeña y universal:

 expr "$string" : "$prefix\(.*\)$suffix" 

Usando @Adrian Frühwirth respuesta:

 function strip { local STRING=${1#$"$2"} echo ${STRING%$"$2"} } 

Úselo así

 HELLO=":hello:" HELLO=$(strip "$HELLO" ":") echo $HELLO # hello 

Usando el operador =~ :

 $ string="hello-world" $ prefix="hell" $ suffix="ld" $ [[ $string =~ $prefix(.*)$suffix ]] && echo "${BASH_REMATCH[1]}" o-wor