Remover palavra específica na variável

Remover palavra específica na variável

Em um bashscript, como posso remover uma palavra de uma string, a palavra seria armazenada em uma variável.

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

Responder1

Usando bashsubstituição de substring (copiado de ksh93):

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

O //substitui todas as ocorrências da substring ( $WORDTOREMOVE) pelo conteúdo entre /e }. Neste caso nada.

Observe as aspas $WORDTOREMOVEpara garantir que o conteúdo seja considerado uma string fixa em vez de um padrão.

Quando a substituição está vazia, /também pode ser omitido: ${FOO//"$WORDTOREMOVE"}.

Para obter informações sobre esta e outras maneiras de trabalhar com strings no bash, consulte a seção10.1. Manipulando StringsdoGuia avançado de script Bash.

Responder2

Tentar:

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

Isso também funciona em ksh93(de onde vem) mkshe zsh.


POSIXamente:

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"

Ele assume que suas palavras são delimitadas por espaços e têm efeitos colaterais que removem espaços antes e depois "$WORDTOREMOVE".

Responder3

Você pode usarsedassim:

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

Responder4

Removendo umpalavrade uma string que representa uma lista de palavras delimitadas por espaços em branco não é tão fácil, porque você precisa decidir o que fazer com o espaçamento de cada lado.

Mesmo em uma representação domesticada onde há sempre um único espaço entre as palavras, é necessário diferenciar vários casos diferentes:

  • palavra no meio: foo MICE bar-> foo bar: palavra e os espaços antes e os espaços depois substituídos por um único espaço.${var/+( )MICE+( )/ }
  • palavra no início: MICE foo bar-> foo bar: palavra e os espaços depois substituídos por nada:${var/MICE+( )}
  • palavra no final: foo bar MICE-> foo bar: palavra e os espaços anteriores substituídos por nada: ${var/+( )MICE}.
  • então há o problema de várias ocorrências sucessivas da palavra where ${var// MICE / }não funcionaria foo MICE MICE barporque a primeira substituição consumiria o espaço que precede o segundo MICE.

(acima usando o ${var/pattern/replacement}operador de ksh93).

Torna-se mais fácil se você adicionar um espaço no início e no final antes de fazer a substituição e removê-los depois, pois assim você poderá cobrir todos os motivos com um operador de substituição:

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

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

Você precisaria shopt -s extglobde bash ou set -o kshglobzsh antecipadamente para suportar esse +([[:space:]])operador ksh88 para corresponder a 1 ou mais caracteres de espaço em branco.

Ou usando zsho próprio extendedglobs( set -o extendedglob) onde o de ksh +(x)se torna x##:

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

É até possível restaurar o espaçamento que estava antes ou depois das palavras com (in zsh; ksh93 teria algo equivalente, não 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% }

Se em vez de uma variável escalar contendo uma representação de uma lista, você tiver uma variável reallista(matriz) variável, como em:

var=(MICE foo MICE MICE bar MICE)

Então o problema é reduzido à remoção de elementos específicos do array, o que se torna trivial com shells com variáveis ​​de array adequadas, como (de onde vem zshessa sintaxe):var=(foo bar)

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

informação relacionada