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.