Eliminar palabra específica en variable

Eliminar palabra específica en variable

En un bashscript, ¿cómo puedo eliminar una palabra de una cadena? La palabra se almacenaría en una variable.

FOO="CATS DOGS FISH MICE"
WORDTOREMOVE="MICE"

Respuesta1

Usando bashreemplazo de subcadenas (copiado de ksh93):

FOO=${FOO//"$WORDTOREMOVE"/}

Reemplaza //todas las apariciones de la subcadena ( $WORDTOREMOVE) con el contenido entre /y }. En este caso nada.

Tenga en cuenta las comillas $WORDTOREMOVEpara asegurarse de que el contenido se tome como una cadena fija en lugar de un patrón.

Cuando el reemplazo está vacío, /también se puede omitir: ${FOO//"$WORDTOREMOVE"}.

Para obtener información sobre esta y otras formas de trabajar con cadenas en bash, consulte la sección10.1. Manipular cadenasdelGuía avanzada de secuencias de comandos Bash.

Respuesta2

Intentar:

$ printf '%s\n' "${FOO//"$WORDTOREMOVE"/}"
CATS DOGS FISH

Esto también funciona en ksh93(de donde viene) mkshy zsh.


POSIX:

FOO="CATS DOGS FISH MICE"
WORDTOREMOVE="MICE"

remove_word() (
  set -f
  IFS=' '

  s=$1
  w=$2

  set -- $1
  for arg do
    shift
    [ "$arg" = "$w" ] && continue
    set -- "$@" "$arg"
  done

  printf '%s\n' "$*"
)

remove_word "$FOO" "$WORDTOREMOVE"

Asume que sus palabras están delimitadas por espacios y tiene un efecto secundario que elimina los espacios antes y después "$WORDTOREMOVE".

Respuesta3

Puedes usarsedcomo esto:

echo $FOO | sed s/"$WORDTOREMOVE"//

Respuesta4

Quitando unopalabrade una cadena que representa una lista de palabras delimitadas por espacios en blanco no es tan fácil, porque es necesario decidir qué hacer con el espacio en cada lado.

Incluso en una representación domesticada donde siempre hay un único espacio entre las palabras, es necesario diferenciar varios casos diferentes:

  • palabra en el medio: foo MICE bar-> foo bar: palabra y los espacios antes y después reemplazados por un solo espacio.${var/+( )MICE+( )/ }
  • palabra al principio: MICE foo bar-> foo bar: palabra y los espacios posteriores reemplazados por nada:${var/MICE+( )}
  • palabra al final: foo bar MICE-> foo bar: palabra y los espacios anteriores reemplazados por nada: ${var/+( )MICE}.
  • luego está el problema de varias apariciones sucesivas de la palabra que ${var// MICE / }no funcionarían foo MICE MICE barporque el primer reemplazo consumiría el espacio que precede al segundo MICE.

(arriba usando el ${var/pattern/replacement}operador de ksh93).

Sin embargo, se vuelve más fácil si agrega un espacio al principio y al final antes de realizar la sustitución y los elimina después, ya que entonces puede cubrir todos los terrenos con un operador de sustitución:

var='MICE foo MICE MICE bar MICE'
word=MICE

var=" $var "
var=${var//+(+([[:space:]])"$word")+([[:space:]])/ }
var=${var# } var=${var% }

Necesitaría shopt -s extglobbash o set -o kshglobzsh de antemano para admitir que +([[:space:]])el operador ksh88 coincida con 1 o más caracteres de espacio en blanco.

O usando zshel propio extendedglobs ( set -o extendedglob) donde ksh +(x)se convierte en x##:

var=${var//([[:space:]]##$word)##[[:space:]]##/ }

Incluso es posible restaurar el espacio que estaba antes o después de las palabras con (en zsh; ksh93 tendría algo equivalente, no bash):

var='MICE foo MICE MICE bar MICE'
word=MICE

set -o extendedglob
var=" $var "
var=${var//(#b)([[:space:]]##$word)##([[:space:]]##)/$match[2]}
var=${var# } var=${var% }

Si en lugar de una variable escalar que contiene una representación de una lista, tienes una variable escalar reallista(matriz) variable, como en:

var=(MICE foo MICE MICE bar MICE)

Luego, el problema se reduce a eliminar elementos específicos de la matriz, lo que se vuelve trivial con shells con variables de matriz adecuadas, como (de donde proviene zshesa sintaxis):var=(foo bar)

var=( ${var:#$word} )

información relacionada