Escape de um caractere de estrela (*) no bash

3

Eu apenas não posso fazer isso. Se * estiver em uma variável, ela será expandida para uma lista de arquivos na pasta atual. echo "*" funciona bem.

#!/bin/bash
c="GRANT ALL ON \*.* TO '$1'@'localhost';"
mysql < $c
exit 0;
    
por gregor 23.07.2010 / 22:21

7 respostas

4

Use aspas simples para sua string:

c='GRANT ALL ON *.* TO';
c="${c} '$1'@'localhost';";

Provavelmente, existe uma maneira melhor de fazer isso, mas incluir $ 1 na sequência tornou estranho

    
por 23.07.2010 / 22:27
8
  1. Sempre coloque aspas duplas em torno das substituições de variáveis, caso contrário, caracteres como espaços e * que aparecem no valor são interpretados pelo shell. Por exemplo, escreva "$c" , não $c .

  2. A sintaxe mysql <"$c" torna mysql executar comandos de um arquivo cujo nome é o valor de $c . O que você está procurando é

    printf '%s\n' "$c" | mysql
    

    ou mais simples, desde que você se lembre das restrições ( $c não deve começar com - , e se ele contiver \ é ok no bash mas não em outras variantes do sh)

    echo "$c" | mysql
    

    Existe outra alternativa que é mais confortável se o comando for multilinha. É chamado de "documento aqui". A string EOF não é especial (embora seja tradicional), qualquer sequência de letras e dígitos serve. A terminação EOF pode não ser precedida por espaços em branco. Você precisa colocar um \ antes de cada $ , \ e ' , a menos que você queira que eles sejam interpretados pelo shell.

    mysql <<EOF
    GRANT ALL ON *.* TO '$1'@'localhost';
    EOF
    
  3. Tenha em atenção que, se o argumento para a shell contiver uma aspa simples, terá um vector de injecção. O snippet a seguir adiciona um \ antes de cada \ e ' .

    set -- "${1//\/\\}"
    set -- "${1//\'/\'}"
    

    Isto é bastante feio, e é por isso que se você for fazer algo complicado, esqueça o uso de um shell e use uma linguagem com ligações SQL reais (perl, python, whatever) onde a biblioteca lida com todas as citações e procedimentos construindo para você.

por 23.07.2010 / 23:01
2

Isso funcionará no bash, sem necessidade de escapar

#!/bin/bash
mysql -u root -e "GRANT ALL ON *.* TO '$1'@'localhost'"
exit 0;
    
por 24.07.2010 / 01:57
1

Primeiro, você precisa imprimir o comando SQL usando echo.

Então você precisa colocar aspas em torno de $c da seguinte forma:

mysql <( echo "$c" )

Caso contrário, o valor de $c será tratado como um comando bash e, portanto, o * será expandido.

Ou uma versão mais simples poderia ser:

mysql -e "$c"
    
por 23.07.2010 / 22:32
1

Não é mais complicado que isso:

#!/bin/bash
c="GRANT ALL ON *.* TO $1@localhost;"
mysql -e "$c"

Ou, se você precisar das aspas simples:

#!/bin/bash
c="GRANT ALL ON *.* TO '$1'@'localhost';"
mysql -e "$c"
    
por 23.07.2010 / 23:35
1

Simples é perfeito! (cite a primeira parte com aspas simples)

#!/bin/bash
c='GRANT ALL ON *.*' "TO '$1'@'localhost';"
mysql < $c
exit 0;

deve ser perfeito também! ($ c citado)

#!/bin/bash
c="GRANT ALL ON *.* TO '$1'@'localhost';"
mysql < "$c"
exit 0;
    
por 24.07.2010 / 00:11
0

O recurso que está lutando contra você é o shell globbing como parte da expansão do nome do caminho. Desabilite isso para resolver o problema principal que você relatou. Em seguida, use a sugestão do Weboide de -e para executar um único comando contido na variável $ c através do MySQL. Felicidades,

[maxwell@elite ~]$ cat me.sh
#!/bin/bash

# disable shell globbing so c variable can be literal
set -f
c="GRANT ALL ON *.* TO '$1'@'localhost';"

echo $c

# enable shell globbing for normal operation
set +f
echo $c
[maxwell@elite ~]$ ./me.sh maxwell
GRANT ALL ON *.* TO 'maxwell'@'localhost';
GRANT ALL ON labserver.etc.0710.tar me.sh Validation.txt TO 'maxwell'@'localhost';
[maxwell@elite ~]$ 
    
por 23.07.2010 / 23:32

Tags