Se você quiser ver variáveis em subprocessos, precisará export deles. Assim:
$ export a=7
$ sh -c 'echo $a'
7
No seu caso, subprocessos (por a e b ) não vêem variáveis do shell pai.
Quando você cria uma string com aspas simples, todas as substituições não funcionam. Você não pode substituir variável ou algo como \n . Será exatamente $a ou \n . Então, string no primeiro caso é exatamente 'echo $ a'. sh -c 'echo $a' criará um novo processo, e esse processo não terá o pai $a , ele terá seu próprio% não inicializado$a, i. e. seqüência vazia. Será apenas a execução de 'echo $a'
No segundo caso, você está usando aspas duplas. A substituição funciona e a sequência torna-se "echo two" antes do subprocesso de execução. Então, é apenas a execução sh -c 'echo two' .
No terceiro caso, $c se torna variável exportada. É uma sintaxe especial que significa «variável de exportação apenas para este comando». Assim, você executa exatamente sh -c 'echo $c' , mas o novo shell conterá $c como uma variável de ambiente. Como $PATH ou $HOME quando você inicia seu shell.