
Em um bash
script, 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 bash
substituiçã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 $WORDTOREMOVE
para 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) mksh
e 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 usarsed
assim:
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 funcionariafoo MICE MICE bar
porque 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 extglob
de bash ou set -o kshglob
zsh antecipadamente para suportar esse +([[:space:]])
operador ksh88 para corresponder a 1 ou mais caracteres de espaço em branco.
Ou usando zsh
o próprio extendedglob
s( 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 zsh
essa sintaxe):var=(foo bar)
var=( ${var:#$word} )