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" .
\n
nesse 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 sh
solução compatível com POSIX é:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echo
argumento. 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 sed
se 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/name
estiver no começo. Nós não precisamos sed
!
Dado que o bash nos fornece variáveis mágicas $PWD
e $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 $HOME
contém barras, mas isso não quebrou nada.
Outras leituras: Guia Avançado de Bash-Scripting .
Se o uso sed
for obrigatório, escape de todos os caracteres .
sed
com o pwd
comando 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 $PS1
jejum: você também pode estar interessado $PROMPT_COMMAND
se estiver mais à vontade em outra linguagem de programação e quiser codificar um prompt compilado.
echo "${PWD/#$HOME/~}"
não substitui o meu $HOME
por ~
. 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, uname
sem 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 $t
está $f
com o [ "${f%$t*}" != "$f" ]
que será avaliado como true se a $f
string 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"