Sostituisci un personaggio con un altro in Bash


223

Devo riuscire a sostituire uno spazio ( ) con un punto ( .) in una stringa in bash.

Penso che sarebbe abbastanza semplice, ma sono nuovo, quindi non riesco a capire come modificare un esempio simile per questo uso.

Risposte:


390

Usa la sostituzione della stringa di shell in linea. Esempio:

foo="  "

# replace first blank only
bar=${foo/ /.}

# replace all blanks
bar=${foo// /.}

Vedi http://tldp.org/LDP/abs/html/string-manipulation.html per maggiori dettagli.


1
Mentre questa soluzione è buona quando si tratta di stringhe brevi (il caso comune, immagino), si può preferire trper stringhe lunghe. Sul mio sistema trsupera bash a partire da stringhe con più di 1000caratteri. Sembra che la complessità temporale di Bash sia peggiore di quella lineare. Un piccolo test: x="$(tr -dc 'a-z \n' </dev/urandom | head -c1M)"; time y="$(tr ' ' \\- <<< "$x")"; time z="${x// /-}". Con una lunghezza della stringa di 1M (= 2 ^ 20) trprese 0.04se prese bash 5.0.11 17s. Con 2M ha trpreso 0.07s(previsto) ma bash ha richiesto 69s(4 volte più lungo per il doppio della lunghezza della stringa).
Socowi,

@Socowi Giocare con 1Mb memorizzato in una variabile non è proprio normale! Fino a più di 10Kb, bash sembra rimanere più veloce del fork tr! ... A seconda della memoria disponibile e delle risorse hw ... Ma hai ragione !: A seconda del tipo di lavoro da svolgere, gli strumenti dedicati rimangono più efficienti!
F. Hauri,

Per i caratteri di escape come le nuove righe, assicurati di cercare$'\n'
user2561747

75

È possibile utilizzare tr, in questo modo:

tr " " .

Esempio:

# echo "hello world" | tr " " .
hello.world

Da man tr:

DESCRIZIONE
     Traduci, stringi e / o elimina i caratteri dall'input standard, scrivendo nell'output standard.


Mentre questo funziona per la domanda come è stata posta, è meno generale della risposta accettata (che funziona sulla sostituzione del carattere e anche sulle stringhe arbitrarie), e coinvolge anche un comando esterno.
Dan Dascalescu,

2
D'altra parte funziona su un file da 2 GB senza caricare l'intera cosa in memoria.
aioobe,

La domanda riguardava "una stringa in bash", non file di dimensioni arbitrarie.
Dan Dascalescu,

52

In bash, puoi eseguire la sostituzione del pattern in una stringa con il ${VARIABLE//PATTERN/REPLACEMENT}costrutto. Utilizzare solo /e non //per sostituire solo la prima occorrenza. Il modello è un modello jolly, come globs di file.

string='foo bar qux'
one="${string/ /.}"     # sets one to 'foo.bar qux'
all="${string// /.}"    # sets all to 'foo.bar.qux'



4

Prova questo per i percorsi:

echo \"hello world\"|sed 's/ /+/g'|sed 's/+/\/g'|sed 's/\"//g'

Sostituisce lo spazio all'interno della stringa tra virgolette doppie con un +canto, quindi sostituisce il+ segno con una barra rovesciata, quindi rimuove / sostituisce le virgolette doppie.

Ho dovuto usare questo per sostituire gli spazi in uno dei miei percorsi in Cygwin.

echo \"$(cygpath -u $JAVA_HOME)\"|sed 's/ /+/g'|sed 's/+/\\/g'|sed 's/\"//g'

2
Esiste già una risposta di due anni che risolve il problema sed. Le virgolette sono irrilevanti.
Chepner,
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.