Diga que eu tenho isso:
str="@test/string"
echo $str
@test/string
echo ${str#@}
test/string
funciona como esperado, mas
echo ${str//\//-}
ksh: ${str//\//-}: bad substitution
falha. (esperado @test-string)
Qual é a maneira correta de substituir/substituir caracteres como este?
echo $KSH_VERSION
KSH version @(#)PD KSH v5.2.14 99/07/13.2
O
pdksh
shell, que é o shell padrão para novos usuários, por exemplo, no OpenBSD, não possui a substituição de parâmetro não padrão que você mencionou.Para substituir todas as correspondências não sobrepostas de algum padrão por alguma nova string, você pode usar
sed
:Observe que isso usa
PATTERN
como uma expressão regular básica POSIX, queREPLACEMENT
deve escapar&
,\1
e outras strings quesed
serão interpretadas de maneiras especiais, e que a substituição do comando retira todos os caracteres de nova linha à direita do final da string.Exemplo:
Nesse caso, quando apenas um único caractere está sendo substituído, pode-se substituir a
sed
substituição pory/\//-/
, ou substituir todo osed
comando pelotr
comandotr / -
.Você também pode optar por escrever um loop de shell:
Neste código,
PATTERN
é um padrão de shell ("padrão de globbing de nome de arquivo"). O código substitui repetidamente a primeira correspondência do padrão na string pela string de substituição, até que não haja mais correspondências. Por causa do loop, não há garantia de que iterações posteriores não executem substituições em strings de substituição inseridas anteriormente.Exemplo:
Yes
${var//pattern/replacement}
é um operador ksh93, enquanto pdksh foi concebido como um clone de ksh88. pdksh como um projeto foi descontinuado, mas sobrevive como é osh
de alguns BSDs, incluindo OpenBSD e MirBSD. MirBSD sh/ksh também chamado de mksh também mantido como um shell portátil e está disponível em muitas distribuições Linux. Ele adicionou esse operador ksh93 em 2008 na versão R33.POSIXAMENTE, para substituir um caractere por outro em uma variável, você pode usar o
tr
utilitário ansliterator, mas precisa alimentar o conteúdo da variável em seu stdin e obter o resultado de seu stdout:(o adicionado
.\n
para contornar o fato de que a substituição de comando remove os caracteres de nova linha à direita).Você também pode usar o operador split+glob para evitar a execução de um comando separado:
Fadado a ser uma maneira melhor, mas: