Eu tenho um comando armazenado em uma variável. Vamos fingir que a variável $i
tem o valor:
cat -nT index.php |grep 'someregex'
Quando tento executar a variável acima, digitando $i
-a falha porque o shell tenta executar a variável inteira como um comando. Eu também tentei usar eval($i)
e colocar $i
backticks.
Como posso fazer o shell executar $i
como se fosse um comando? E por que não está funcionando da mesma maneira que.
$i='echo hi'; $i
É porque eu tive que meio que invadir as aspas simples? (Porque você não pode aninhá-los.) Atualmente, minha solução é
echo $i > /foo; . /foo
Mas não quero criar um arquivo apenas para isso, apenas para excluí-lo mais tarde.
O que quero dizer com "hackeei as aspas simples é o que fiz:
$i='cat index.php | grep -P '"'"'MYREGEXHERE'"'"
Respostas:
Resposta curta: consulte BashAQ # 50: Estou tentando colocar um comando em uma variável, mas os casos complexos sempre falham! .
Resposta longa: é por causa da ordem em que o bash analisa a linha de comando. Especificamente, ele procura coisas como pipes e redirecionamentos antes de expandir valores variáveis, e não volta e procura novamente pipes etc. nos valores expandidos. Essencialmente, as variáveis são substituídas na metade do processo de análise, portanto, o valor é analisado apenas na metade antes de ser executado.
Para resolver isso, você precisa responder à pergunta de @ slhck: por que o comando é armazenado em uma variável em primeiro lugar? Qual é o problema real que você está tentando resolver? Dependendo do objetivo real, existem várias soluções possíveis:
Não o armazene em uma variável, apenas execute-o diretamente. O armazenamento de comandos para uso posterior é complicado e, se você realmente não precisa, simplesmente não precisa.
Use uma função em vez de uma variável. Afinal, é para isso que eles servem:
A principal desvantagem disso é que você não pode criar a função dinamicamente - você não pode incluir ou excluir condicionalmente o código da função (embora a própria função possa ter elementos condicionais que são selecionados quando são executados).
Use
eval
. Isso deve ser considerado um último recurso, pois é fácil obter um comportamento inesperado. Essencialmente, ele executa o comando através de outra passagem de análise completa, para que todos os pipes etc. tenham todo o significado - mas também significa que partes do comando que você pensou serem apenas dados também serão analisadas e talvez executadas. Os nomes de arquivos que contêm metacaracteres de shell (tubo, ponto-e-vírgula, aspas / apóstrofo, etc.) podem ter efeitos estranhos e às vezes perigosos. Se você usareval
, pelo menos aspas duplas na string, caso contrário, seu conteúdo será essencialmente analisado uma vez e meia, com resultados ainda mais estranhos.Edição: Outra abordagem padrão de armazenar um comando em uma variável é usar uma matriz em vez de uma variável simples. Isso permite que você armazene um comando com argumentos complexos (por exemplo, contendo espaços) sem problemas, mas não armazena itens como pipes e redirecionamentos. Portanto, a abordagem de matriz não será útil nesse caso específico.
fonte
eval
método. Isso me impediu de fazer a mesma pergunta :). Eu tenho algo assimsudo rsync -aAHXi -n --delete-excluded --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/lost+found","/mnt/DATA/*","/var/log/*","/var/swap","/var/cache/apt/archives/*.deb"} -e ssh root@piac_wireless:/ /home/mrx/Docs/RPi/backup/piac/piac_usb-root
que não estava executando as exclusões corretamente.eval
para isso - há muitas maneiras de dar errado. Uma matriz seria a melhor maneira de fazer isso. Veja aqui , aqui e aqui para exemplos.Isso deve funcionar:
Cuidado que
eval
introduz vulnerabilidades em potencial e situações inesperadas de comportamento deve ser usado, se houver, com cuidado extra.fonte
eval
, realmente precisará usar aspas duplas (eval "$i"
) para evitar efeitos extra-extra-estranhos. Por exemplo, tente isso coma="cat -nT index.php |grep ' .* '"
(ou seja, a regex deve corresponder a dois espaços com qualquer sequência de caracteres entre eles) e veja o que realmente acontece. Para crédito extra, explique por que isso acontece.Ao declarar a variável, você não deve usar o cifrão como prefixo.
Tente o seguinte:
fonte