@ruakh como escrevo esta declaração com uma condição ou. Só se eu quiser substituir Suzi ou Marry por uma nova string.
precisa saber é o seguinte
3
@ Priyatham51: Não há recurso embutido para isso. Apenas substitua um e depois o outro.
Ruakh
4
@ Bu: Não, porque \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/.)
ruach
25
Para deixar claro, como isso me confundiu um pouco, a primeira parte deve ser uma referência variável. Você não pode fazer echo ${my string foo/foo/bar}. Você precisariainput="my string foo"; echo ${input/foo/bar}
Henrik N
2
@mgutt: Esta resposta está vinculada à documentação relevante. A documentação não é perfeita - por exemplo, em vez de mencionar //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.
ruakh 28/11/19
208
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"
Qual é o sentido de ter uma resposta que duplica a aceita, em vez de editá-la com a opção de substituição global? E adicionar que regexps são suportados, enquanto estiver nele. E explicando o que há com "Má substituição". Você tem pontos suficientes, @ Kevin :)
Dan Dascalescu
6
Parece que os dois responderam exatamente no mesmo minuto: O
Jamie Hutber 03/11/19
76
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/")
Eu recebi o seguinte: $ echo $ (echo $ firstString | sed 's / Suzi / $ secondString / g') Adoro $ secondString e casar
Qstnr_La
2
@Qstnr_La usar aspas duplas para substituição de variáveis:result=$(echo $firstString | sed "s/Suzi/$secondString/g")
emc
1
Mais 1 para mostrar como gerar também uma variável. Obrigado!
Chef Pharaoh
2
Corrigi as aspas simples e também adicionei as aspas ausentes ao redor do 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.).
Tripleee 17/07/2018
No sh (AWS Codebuild / Ubuntu sh), descobri que precisava de uma única barra no final, não uma dupla. Vou editar o comentário, pois os comentários acima também mostram uma única barra.
Você realmente não precisa de Sed para isso; O Bash suporta esse tipo de substituição nativamente.
Ruakh
12
Eu acho que isso está marcado como "bash", mas veio aqui porque precisava de algo simples para outro shell. Esta é uma boa alternativa sucinta ao que wiki.ubuntu.com/… fez parecer que eu precisaria.
Natevw 30/09/14
3
Isso funciona muito bem para ash / dash ou qualquer outro POSIX sh.
Yoshua Wuyts 21/03
2
Eu recebo o erro sed: -e expressão # 1, caractere 9: opção desconhecida para `s
Nam G VU
1
Primeira resposta que funciona com stdin, ótima para strings de pipelining.
Dinei
46
É 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.
Essa resposta me impediu de usar 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?
Mark Haferkamp
1
@ MarkHaferkamp Veja isso no link "leitura adicional recomendada". Sobre "escapar do ~": 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.
Camilo Martin
O link "leitura adicional" explica o "#". No Bash 4.3.30, 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 .
Mark Haferkamp
@ MarkHaferkamp Whoa, você está totalmente certo, meu mal. Atualizará a resposta agora.
Camilo Martin
1
@MarkHaferkamp Bash e suas armadilhas obscuras ...: P
Camilo Martin
19
Se amanhã você decidir que não ama Marry, ela também poderá ser substituída:
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}
Até que cheguei ao seu exemplo, eu tinha entendido a ordem ao contrário. Isso ajudou a esclarecer o que está acontecendo
raghav710
5
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 loveSuzi 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.
Respostas:
Para substituir a primeira ocorrência de um padrão por uma determinada sequência, use :
${parameter/pattern/string}
Para substituir todas as ocorrências, use :
${parameter//pattern/string}
(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" .
fonte
\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 quererSTRING//
- substituí-all - em vez de apenasSTRING/
.)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:
Isso substituirá apenas a primeira ocorrência; para substituir todos eles, dobre a primeira barra:
fonte
Para o Dash, todas as postagens anteriores não estão funcionando
A
sh
solução compatível com POSIX é:fonte
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:
fonte
É melhor usar o bash do que
sed
se as strings tiverem caracteres RegExp.É 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:
Nisso:
Mas somente se
/home/name
estiver no começo. Nós não precisamossed
!Dado que o bash nos fornece variáveis mágicas
$PWD
e$HOME
, podemos: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 .fonte
sed
com opwd
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:
Deve haver 50 maneiras de deixar seu amante.
fonte
Desde que eu não posso adicionar um comentário. @ruaka Para tornar o exemplo mais legível, escreva-o assim
fonte
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:Resultado:
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.fonte
Eu sei que isso é antigo, mas como ninguém mencionou o uso do awk:
fonte
fonte