Substitua um caractere por outro no Bash

223

Eu preciso ser capaz de substituir um espaço ( ) por um ponto ( .) em uma string no bash.

Eu acho que isso seria bem simples, mas sou novo, portanto não consigo descobrir como modificar um exemplo semelhante para esse uso.

Brian Leishman
fonte

Respostas:

390

Use a substituição de cadeia de shell em linha. Exemplo:

foo="  "

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

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

Veja http://tldp.org/LDP/abs/html/string-manipulation.html para mais detalhes.

Brian Clapper
fonte
1
Embora essa solução seja boa ao lidar com strings curtas (o caso comum, eu acho), pode-se preferir trstrings longas. No meu sistema trsupera o bash começando em strings com mais de 1000caracteres. Parece que a complexidade do tempo do bash é pior que linear. Um pequeno teste: x="$(tr -dc 'a-z \n' </dev/urandom | head -c1M)"; time y="$(tr ' ' \\- <<< "$x")"; time z="${x// /-}". Com um comprimento de string de 1M (= 2 ^ 20), trlevou 0.04se o bash 5.0.11 levou 17s. Com 2M trlevou 0.07s(esperado), mas o bash levou 69s(4 vezes mais que o dobro do comprimento da string).
Socowi 21/12/19
@Socowi Jogando com 1Mb armazenado em uma variável não é realmente comum! Até mais de 10 KB, o bash parece ficar mais rápido do que o bifurcado tr! ... Dependendo da memória disponível e dos recursos hw ... Mas você está certo !: Dependendo do tipo de trabalho a ser feito, as ferramentas dedicadas permanecem mais eficientes!
F. Hauri
Para caracteres de escape, como novas linhas, certifique-se de procurar$'\n'
user2561747
75

Você poderia usar tr, assim:

tr " " .

Exemplo:

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

De man tr:

DESCRIÇÃO
     Traduza, comprima e / ou exclua caracteres da entrada padrão, gravando na saída padrão.

aioobe
fonte
Enquanto isso funciona para a pergunta como foi feita, é menos geral que a resposta aceita (que funciona na substituição de caracteres e também em seqüências arbitrárias), e também envolve um comando externo.
Dan Dascalescu 15/10
2
Por outro lado, ele funciona em um arquivo de 2GB sem carregar a coisa toda na memória.
aioobe
A pergunta era sobre "uma string no bash", e não arquivos arbitrariamente grandes.
Dan Dascalescu 15/10
52

No bash, você pode fazer a substituição de padrões em uma sequência com a ${VARIABLE//PATTERN/REPLACEMENT}construção. Use apenas /e não //para substituir apenas a primeira ocorrência. O padrão é um padrão curinga, como globs de arquivo.

string='foo bar qux'
one="${string/ /.}"     # sets one to 'foo.bar qux'
all="${string// /.}"    # sets all to 'foo.bar.qux'
Gilles 'SO- parar de ser mau'
fonte
24

Tente isto

 echo "hello world" | sed 's/ /./g' 
Roubar
fonte
6

Use substituição de parâmetro:

string=${string// /.}
Fritz G. Mehner
fonte
4

Tente isto para caminhos:

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

Ele substitui o espaço dentro da sequência de aspas duplas por um +canto, substitui o +sinal por uma barra invertida e remove / substitui as aspas duplas.

Eu tive que usar isso para substituir os espaços em um dos meus caminhos em Cygwin.

echo \"$(cygpath -u $JAVA_HOME)\"|sed 's/ /+/g'|sed 's/+/\\/g'|sed 's/\"//g'
dsrdakota
fonte
2
Já existe uma resposta de dois anos que resolve o problema sed. As aspas são irrelevantes.
Chepner # 22/13