Substituir uma subcadeia por outra seqüência no script de shell

Eu tenho “Eu amo Suzi e Marry” e eu quero mudar “Suzi” para “Sara”.

#!/bin/bash firstString="I love Suzi and Marry" secondString="Sara" # do something... 

O resultado deve ser assim:

 firstString="I love Sara and Marry" 

   

Para replace a primeira ocorrência de um padrão por uma determinada string, use ${ parameter / pattern / string } :

 #!/bin/bash firstString="I love Suzi and Marry" secondString="Sara" echo "${firstString/Suzi/$secondString}" # prints 'I love Sara and Marry' 

Para replace todas as ocorrências, use ${ parameter // pattern / string } :

 message='The secret code is 12345' echo "${message//[0-9]/X}" # prints 'The secret code is XXXXX' 

(Isto está documentado no Manual de Referência do Bash , §3.5.3 “Expansão do Parâmetro do Shell” .)

Note que este recurso não é especificado por POSIX – é uma extensão Bash – então nem todos os shells Unix o implementam. Para a documentação relevante do POSIX, consulte Especificações técnicas básicas padrão do grupo aberto, edição 7 , o volume Shell & Utilities , §2.6.2 “Expansão do parâmetro” .

Isso pode ser feito inteiramente com manipulação de string bash:

 first="I love Suzy and Mary" second="Sara" first=${first/Suzy/$second} 

Isso replaceá apenas a primeira ocorrência; para substituí-los todos, o dobro da primeira barra:

 first="Suzy, Suzy, Suzy" second="Sara" first=${first//Suzy/$second} # first is now "Sara, Sara, Sara" 

tente isto:

  sed "s/Suzi/$secondString/g" < <<"$firstString" 

É melhor usar bash do que sed se as strings tiverem caracteres RegExp.

 echo ${first_string/Suzi/$second_string} 

É portátil para o Windows e funciona com pelo menos a mesma idade que o Bash 3.1.

Para mostrar que você não precisa se preocupar muito em escaping, vamos transformar isso:

 /home/name/foo/bar 

Nisso:

 ~/foo/bar 

Mas somente se /home/name estiver no começo. Nós não precisamos de sed !

Dado que o bash nos dá as variables ​​mágicas $PWD e $HOME , podemos:

 echo "${PWD/#$HOME/\~}" 

EDIT: Obrigado por Mark Haferkamp nos comentários para a nota sobre cotação / escape ~ . *

Observe como a variável $HOME contém barras, mas isso não quebrou nada.

Leitura adicional: Advanced Bash-Scripting Guide .
Se usar sed for uma obrigação, assegure-se de escaping de todos os personagens .

Para o Dash, todas as postagens anteriores não estão funcionando

A solução compatível com POSIX sh é:

 result=$(echo "$firstString" | sed "s/Suzi/$secondString//") 

Se amanhã você decidir que não ama Marry, ela também pode ser substituída:

 today=$( /tmp/lovers.txt 

Deve haver 50 maneiras de deixar seu amante.