Sostituisci una sottostringa per un’altra stringa nello script della shell

Ho “I love Suzi and Marry” e voglio cambiare “Suzi” in “Sara”.

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

Il risultato deve essere così:

 firstString="I love Sara and Marry" 

Per sostituire la prima occorrenza di un pattern con una determinata stringa, usa ${ parameter / pattern / string } :

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

Per sostituire tutte le occorrenze, usa ${ parameter // pattern / string } :

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

(Questo è documentato nel Bash Reference Manual , §3.5.3 “Shell Parameter Expansion” .)

Nota che questa caratteristica non è specificata da POSIX: è un’estensione Bash, quindi non tutte le shell Unix lo implementano. Per la documentazione POSIX pertinente, vedere Specifiche tecniche standard di Open Group, numero 7 , il volume Shell & Utilities , §2.6.2 “Parameter Expansion” .

Questo può essere fatto interamente con la manipolazione della stringa bash:

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

Questo sostituirà solo la prima occorrenza; per sostituirli tutti, raddoppia la prima barra:

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

prova questo:

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

È meglio usare bash piuttosto che sed se le stringhe hanno caratteri RegExp.

 echo ${first_string/Suzi/$second_string} 

È portatile per Windows e funziona con almeno vecchio come Bash 3.1.

Per dimostrare che non ti devi preoccupare molto di evadere, facciamo in modo che:

 /home/name/foo/bar 

In questo:

 ~/foo/bar 

Ma solo se /home/name è all’inizio. Non abbiamo bisogno di sed !

Dato che bash ci fornisce variabili magiche $PWD e $HOME , possiamo:

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

EDIT: Grazie per Mark Haferkamp nei commenti per la nota su quoting / escaping ~ . *

Nota come la variabile $HOME contiene barre ma questo non ha infranto nulla.

Ulteriori letture: Guida avanzata di Bash-Scripting .
Se usare sed è un must, assicurati di sfuggire a ogni personaggio .

Per Dash tutti i post precedenti non funzionano

La soluzione POSIX sh compatibile è:

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

Se domani deciderai di non amare Marry, potrà anche essere sostituita:

 today=$( /tmp/lovers.txt 

Ci devono essere 50 modi per lasciare il tuo amante.