Eu tenho "Eu amo Suzi e me case" e quero mudar "Suzi" para "Sara".
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
O resultado deve ser assim:
firstString="I love Sara and Marry"
Eu tenho "Eu amo Suzi e me case" e quero mudar "Suzi" para "Sara".
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
O resultado deve ser assim:
firstString="I love Sara and Marry"
Respostas:
Para substituir a primeira ocorrência de um padrão por uma determinada sequência, use :${parameter/pattern/string}
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
echo "${firstString/Suzi/$secondString}"
# prints 'I love Sara and Marry'
Para substituir todas as ocorrências, use :${parameter//pattern/string}
message='The secret code is 12345'
echo "${message//[0-9]/X}"
# prints 'The secret code is XXXXX'
(Isso está documentado no Manual de Referência do Bash , §3.5.3 "Expansão dos parâmetros do shell" .)
Observe que esse recurso não é especificado pelo POSIX - é uma extensão do Bash -, portanto, nem todos os shells do Unix o implementam. Para obter a documentação relevante do POSIX, consulte Especificações Técnicas Básicas do Open Group, Edição 7 , volume Shell & Utilities , §2.6.2 "Expansão de parâmetros" .
\nnesse contexto se representaria, não uma nova linha. No momento, não tenho o Bash à mão para testar, mas você deve escrever algo como $STRING="${STRING/$'\n'/<br />}",. (Embora você provavelmente vai querer STRING//- substituí-all - em vez de apenas STRING/.)
echo ${my string foo/foo/bar}. Você precisariainput="my string foo"; echo ${input/foo/bar}
//diretamente, ela menciona o que acontece "Se o padrão começa com ' /'" (o que nem é preciso, pois o restante dessa frase assume que o extra /não é realmente parte do o padrão) - mas não conheço nenhuma fonte melhor.
Isso pode ser feito inteiramente com a manipulação de strings do bash:
first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}
Isso substituirá apenas a primeira ocorrência; para substituir todos eles, dobre a primeira barra:
first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}
# first is now "Sara, Sara, Sara"
Para o Dash, todas as postagens anteriores não estão funcionando
A shsolução compatível com POSIX é:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echoargumento. Funciona enganosamente sem citar com strings simples, mas quebra facilmente em qualquer string de entrada não trivial (espaçamento irregular, metacaracteres de shell, etc.).
tente isto:
sed "s/Suzi/$secondString/g" <<<"$firstString"
É melhor usar o bash do que sedse as strings tiverem caracteres RegExp.
echo ${first_string/Suzi/$second_string}
É portátil para Windows e funciona com pelo menos a idade do Bash 3.1.
Para mostrar que você não precisa se preocupar muito com a fuga, vamos transformar isso:
/home/name/foo/bar
Nisso:
~/foo/bar
Mas somente se /home/nameestiver no começo. Nós não precisamos sed!
Dado que o bash nos fornece variáveis mágicas $PWDe $HOME, podemos:
echo "${PWD/#$HOME/\~}"
EDIT: Obrigado por Mark Haferkamp nos comentários para a nota sobre citação / escape ~. *
Observe como a variável $HOMEcontém barras, mas isso não quebrou nada.
Outras leituras: Guia Avançado de Bash-Scripting .
Se o uso sedfor obrigatório, escape de todos os caracteres .
sedcom o pwdcomando para evitar definir uma nova variável cada vez que meu personalizado $PS1é executado. O Bash fornece uma maneira mais geral do que variáveis mágicas para usar a saída de um comando para substituição de string? Quanto ao seu código, tive que escapar do ~para impedir que o Bash o expandisse para $ HOME. Além disso, o que o #comando faz?
~": observe como citei as coisas. Lembre-se de sempre citar coisas! E isso não funciona apenas para variáveis mágicas: qualquer variável é capaz de substituições, obtendo o comprimento da string e muito mais, no bash. Parabéns por tentar o seu $PS1jejum: você também pode estar interessado $PROMPT_COMMANDse estiver mais à vontade em outra linguagem de programação e quiser codificar um prompt compilado.
echo "${PWD/#$HOME/~}"não substitui o meu $HOMEpor ~. Substituindo ~por \~ou '~'funciona. Qualquer um desses trabalhos no Bash 4.2.53 em outra distribuição. Você pode atualizar sua postagem para citar ou escapar da ~para uma melhor compatibilidade? O que eu quis dizer com a minha pergunta "variáveis mágicas" foi: Posso usar a substituição de variáveis do Bash na saída, por exemplo, unamesem salvá-la como variável primeiro? Quanto ao meu pessoal $PROMPT_COMMAND, é complicado .
Se amanhã você decidir que não ama Marry, ela também poderá ser substituída:
today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txt
Deve haver 50 maneiras de deixar seu amante.
Desde que eu não posso adicionar um comentário. @ruaka Para tornar o exemplo mais legível, escreva-o assim
full_string="I love Suzy and Mary"
search_string="Suzy"
replace_string="Sara"
my_string=${full_string/$search_string/$replace_string}
or
my_string=${full_string/Suzy/Sarah}
O método puro de shell POSIX , que, diferentemente da resposta baseada em Roman Kazanovskyi ,sed não precisa de ferramentas externas, apenas as expansões de parâmetros nativas do próprio shell . Observe que nomes longos de arquivos são minimizados para que o código caiba melhor em uma linha:
f="I love Suzi and Marry"
s=Sara
t=Suzi
[ "${f%$t*}" != "$f" ] && f="${f%$t*}$s${f#*$t}"
echo "$f"
Resultado:
I love Sara and Marry
Como funciona:
Remova o menor padrão de sufixo. "${f%$t*}"retorna " I love" se o sufixo $t" Suzi*" estiver em $f" ". I love Suzi and Marry
Mas se t=Zelda, então, "${f%$t*}"não excluirá nada e retornará toda a cadeia " I love Suzi and Marry".
Isso é usado para testar se $testá $fcom o [ "${f%$t*}" != "$f" ]que será avaliado como true se a $fstring contiver " Suzi*" e false se não.
Se o teste retornar verdadeiro , construa a sequência desejada usando Remover o menor padrão de sufixo ${f%$t*} " I love" e Remover o menor padrão de prefixo ${f#*$t} " and Marry", com a segunda sequência $s" Sara" no meio.
Eu sei que isso é antigo, mas como ninguém mencionou o uso do awk:
firstString="I love Suzi and Marry"
echo $firstString | awk '{gsub("Suzi","Sara"); print}'
echo [string] | sed "s/[original]/[target]/g"