Existem várias maneiras de substituir caracteres em uma variável.
A maneira mais curta que descobri é tr
até agora:
OUTPUT=a\'b\"c\`d_123and_a_lot_more
OUTPUT=$(echo "$OUTPUT"|tr -d "'\`\"")
echo $OUTPUT
Existe uma maneira mais rápida? E é este citando-seguro para citações como '
, "
e `si?
tr
. O PE do BASH é bom, mas tr é muito mais rápido nesse caso. por exemplo,echo "$OUTPUT" | tr -dc '[[:alpha:]]'
desde que você quer ter alphanumerics únicaecho "$OUTPUT"
. Ou melhor:printf "%s\n" "$OUTPUT"
. (O que acontece quandoOUTPUT="-n"
?)Respostas:
Vamos ver. O mais curto que posso apresentar é uma emenda da sua
tr
solução:Outras alternativas incluem a substituição de variável já mencionada, que pode ser mais curta do que a mostrada até agora:
E é
sed
claro que isso é mais longo em termos de caracteres:Não tenho certeza se você quer dizer o menor tempo ou o tempo gasto. Em termos de comprimento, esses dois são os mais curtos possíveis (ou, de qualquer maneira,) quando se trata de remover esses caracteres específicos. Então, qual é o mais rápido? Testei definindo a
OUTPUT
variável para o que você tinha no seu exemplo, mas repeti várias dezenas de vezes:Como você pode ver, o
tr
é claramente o mais rápido, seguido de pertosed
. Além disso, parece que o usoecho
é realmente um pouco mais rápido que o uso<<<
:Como a diferença é pequena, executei os testes acima 10 vezes para cada um dos dois, e o mais rápido é realmente o que você tinha para começar:
No entanto, isso muda quando você leva em conta a sobrecarga de atribuir a uma variável, aqui, usar
tr
é um pouco mais lenta que a simples substituição:Portanto, em conclusão, quando você simplesmente deseja visualizar os resultados, use,
tr
mas se quiser reatribuir a uma variável, o uso dos recursos de manipulação de string do shell é mais rápido, pois evita a sobrecarga de executar um subshell separado.fonte
OUTPUT
, você terá que conta para substituição de comando sub-shell sobrecarga envolvida natr
esed
soluçõesOUTPUT="${OUTPUT//[`\"\']/}"
não envolve a substituição de comandoVocê poderia usar substituição de variável :
Use essa sintaxe:
${parameter//pattern/string}
para substituir todas as ocorrências do padrão pela sequência.fonte
echo ${OUTPUT//[`\"\']/x}
givesaxbxcxa
No bash ou zsh é:
Observe que
${VAR//PATTERN/}
remove todas as instâncias do padrão. Para obter mais informações, expansão do parâmetro bashEssa solução deve ser mais rápida para cadeias curtas, porque não envolve a execução de nenhum programa externo. No entanto, para strings muito longas, o oposto é verdadeiro - é melhor usar uma ferramenta dedicada para operações de texto, por exemplo:
fonte
tr
é mais rápido. Regexes e globs são caros e, embora não haja nenhum programa externo aqui, o bash sempre será mais lento do que algo parecidotr
.tr
ganha (veja minha resposta). Concordo que dependerá de muitos fatores, mas é exatamente por isso que você não pode dizer qual deles vence sem realmente testá-lo.Se, por acaso, você estiver apenas tentando manipular cotações para reutilizar o shell, poderá fazer isso sem removê-las, e também é simples:
Essa função shell cita qualquer matriz arg que você a entrega e incrementa sua saída por argumento iterável.
Aqui está com alguns argumentos:
RESULTADO
Essa saída é da
dash
qual tipicamente aspas seguras saem entre aspas'"'"'
.bash
faria'\''
.Substituir uma seleção de bytes únicos, sem espaço em branco e não nulos por outro byte único provavelmente pode ser feito mais rapidamente em qualquer shell POSIX com
$IFS
e$*
.RESULTADO
Aí eu apenas
printf
para que você possa ver, mas é claro, se eu tivesse feito:... ao invés do valor do
printf
comando$var
, seria o que você vê na saída.Quando
set -f
instruo o shell a não glob - caso a string contenha caracteres que possam ser interpretados como padrões glob. Eu faço isso porque o analisador de shells expande os padrões glob depois de executar a divisão de campo nas variáveis. globbing pode ser reativado comoset +f
. Em geral - em scripts - acho útil definir meu estilo como:E, em seguida, para ativar explicitamente englobamento com
set +f
em qualquer linha que eu poderia desejar.A divisão do campo ocorre com base nos caracteres em
$IFS
.Existem dois tipos de
$IFS
valores -$IFS
espaço em branco e$IFS
não-espaço em branco.$IFS
os campos delimitados por espaço em branco (espaço, tabulação, nova linha) são especificados para eleger, por sequência, um único campo (ou nenhum, se não precederem outra coisa) - então ...Mas todos os outros são especificados para avaliar um único campo por ocorrência - eles não são truncados.
Todas as expansões variáveis são, por padrão,
$IFS
matrizes de dados delimitadas - elas são divididas em campos separados de acordo com$IFS
. Ao"
citar uma, você substitui a propriedade da matriz e a avalia como uma única sequência.Então, quando eu faço ...
Estou definindo a matriz de argumentos do shell para os muitos
$IFS
campos delimitados gerados pela$var
expansão do. Quando é expandido, seus valores constituintes para os caracteres contidos$IFS
são perdidos - eles são apenas separadores de campo agora - eles são\0NUL
."$*"
- como outras expansões variáveis de aspas duplas - também substitui as qualidades de divisão de campos de$IFS
. Mas, além disso , ele substitui o primeiro byte no$IFS
para cada campo delimitado em"$@"
. Então, porque"
foi o primeiro valor em$IFS
todos os delimitadores subseqüentes"
em que se tornou"$*"
. E a"
necessidade também não está presente$IFS
quando você a divide. Você poderia alterar$IFS
depoisset -- $args
para outro valor completamente e seu novo primeiro byte apareceria para os delimitadores de campo em"$*"
. Além disso, você pode remover todos os traços deles como:RESULTADO
fonte
tr
em qualquer shell, mas a diferença é duvidosabash
para o${var//$c/$newc/}
caso. Espero que, mesmo nesse caso, seja mais rápido em alguma margem, mas geralmente não me preocupo com isso porque, para essas coisas, eu sempre usodash
- o que é mais rápido em ordens de grandeza em todos os aspectos. E, portanto, é difícil comparar.bash
-time (IFS=\"\'`; set -- $var; printf %s "$*")
etime (var=${var//\'`/\"/})
ambos resultam em0.0000s
resultados para todos os campos. Estou fazendo algo errado, você acha? Deveria haver uma barra invertida antes da citação lá em cima, mas não sei como colocar uma citação em um campo de código de comentário.