Sostituzione di alcuni caratteri in una stringa con un altro carattere


279

Ho una stringa come AxxBCyyyDEFzzLMN e voglio sostituire tutte le occorrenze di x , y , e z con _ .

Come posso raggiungere questo obiettivo?

So che echo "$string" | tr 'x' '_' | tr 'y' '_'avrebbe funzionato, ma voglio farlo in una volta sola, senza usare le pipe.


Volevi sostituire una sequenza di x, y o z consecutivi con un carattere di sottolineatura o volevi sostituire ogni x, y o z con un carattere di sottolineatura? Inoltre, che dire delle sequenze miste, come AxyzB? Tre trattini bassi o uno?
David Z,

tr '[xyz]'sostituirà [e ]anche. L'argomento dovrebbe essere semplicemente un elenco di caratteri (anche se intervalli come quelli a-zvanno bene, e in alcune implementazioni, classi di caratteri POSIX come [:digit:]).
Tripleee,

Risposte:


329
echo "$string" | tr xyz _

sostituirà ogni ricorrenza di x, yo zcon _, dando A__BC___DEF__LMNnel tuo esempio.

echo "$string" | sed -r 's/[xyz]+/_/g'

sostituirà ricorrenze ricorrenti di x, yo zcon una sola _, dando A_BC_DEF_LMNnel tuo esempio.


19
Su Mac, ho ottenuto: sed: opzione illegale - r utilizzo: sed script [-Ealn] [-i extension] [file ...] sed [-Ealn] [-i extension] [-e script]. .. [-f script_file] ... [file ...]
catanore,

Ho una stringa che contiene ,[]{}()~caratteri. Voglio sostituirlo con ogni personaggio speciale sfuggito a '\'come potrei farlo con oneshot?
Inckka,

2
@halakala Mac viene fornito con una versione leggermente diversa di sed. Vedi questa domanda: unix.stackexchange.com/questions/13711/… Invece puoi installare "gnu-sed" con il gestore di pacchetti Homebrew quindi usare il gsedbinario: $ brew install gnu-sedthen$ gsed -r 's/[xyz]+/_/g'
John Kary

6
Su * BSD (e quindi su OSX), sed -Eè (sostanzialmente) equivalente a sed -rsu molte distro Linux, se usi sed 's/[xyz][xyz]*/_/g'non hai bisogno dell'opzione. Naturalmente, questo equivale a tr -s xyz _quindi non c'è davvero bisogno di sedqui.
Tripleee,

@inckka Non puoi usarlo tr. sed 's/[][{}()~,]/\\&/g'ma davvero, fai una nuova domanda se hai una domanda di follow-up (sentiti libero di ricollegarti qui per riferimento, ovviamente). Per inciso, ,e ~non sono metacaratteri regex (sebbene ~venga espanso $HOMEin alcune posizioni da Bash e da altre conchiglie; non shcomunque).
Tripleee,

286

Utilizzando l' espansione dei parametri Bash :

orig="AxxBCyyyDEFzzLMN"
mod=${orig//[xyz]/_}

7
Sostituzione
errata

1
@Alexey, il mio esempio funziona per me (bash 4.3.11 (1) -release). Assicurati di utilizzare bash. Altre shell potrebbero non funzionare (anche se alcune lo faranno).
Matthew Flaschen,

Grazie @MatthewFlaschen. Questo era esattamente ciò di cui avevo bisogno per fare un sostituto di sed per un percorso assoluto in uno script bash (la sostituzione di / con \ / così sed lo accetta).
Ryan G,

1
@RyanG perché usarlo sedse bash ha una sostituzione integrata?
MestreLion

@MestreLion Potrebbe essere andato storto, ma dovevo sostituire un nome di variabile standard in un mucchio di file con un percorso assoluto, per il quale stavo usando la sostituzione sul posto di sed. ma non puoi avere "/" senza sfuggire al comando. Stavo mettendo insieme le operazioni in bash. Non sarebbe questo il modo migliore per manipolare una stringa in bash?
Ryan G,

111

Questo link potrebbe essere utile:

http://tldp.org/LDP/abs/html/string-manipulation.html

In generale,

Per sostituire la prima corrispondenza di $ sottostringa con $ sostituzione:

${string/substring/replacement}

Per sostituire tutte le partite di $ sottostringa con $ sostituzione:

${string//substring/replacement}

EDIT: si noti che questo vale per una variabile denominata $ stringa.


16
Si noti che funziona su una variabile denominata "stringa" non sulla stringa letterale.
Mattdm,

1
il più utile, poiché contiene riferimenti.
Os3,

La soluzione migliore e più breve.
Northtree

8
read filename ;
sed -i 's/letter/newletter/g' "$filename" #letter

^ usa tutti questi di cui hai bisogno e puoi creare la tua crittografia BASIC


5

Ecco una soluzione con espansione dei parametri della shell che sostituisce più occorrenze contigue con una singola _:

$ var=AxxBCyyyDEFzzLMN
$ echo "${var//+([xyz])/_}"
A_BC_DEF_LMN

Si noti che il motivo richiede una corrispondenza estesa del motivo, attivata con+(pattern)

shopt -s extglob

In alternativa, con l' -sopzione ("squeeze") di tr:

$ tr -s xyz _ <<< "$var"
A_BC_DEF_LMN
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.