Digamos se eu escrevi um programa com a seguinte linha:
int main(int argc, char** argv)
Agora ele sabe quais argumentos de linha de comando são passados para ele, verificando o conteúdo de argv
.
O programa pode detectar quantos espaços entre os argumentos? Como quando eu digito isso no bash:
ibug@linux:~ $ ./myprog aaa bbb
ibug@linux:~ $ ./myprog aaa bbb
O ambiente é um Linux moderno (como o Ubuntu 16.04), mas suponho que a resposta deva se aplicar a qualquer sistema compatível com POSIX.
Em geral, não. A análise da linha de comando é feita pelo shell, que não disponibiliza a linha não analisada para o programa chamado. Na verdade, seu programa pode ser executado a partir de outro programa que criou o argv não analisando uma string, mas construindo uma matriz de argumentos programaticamente.
Não faz sentido falar de "espaços entre argumentos"; isso é um conceito de shell.
O trabalho de um shell é pegar linhas inteiras de entrada e transformá-las em arrays de argumentos para iniciar os comandos. Isso pode envolver a análise de strings entre aspas, expansão de variáveis, curingas de arquivo e expressões de til e muito mais. O comando é iniciado com uma
exec
chamada de sistema padrão, que aceita um vetor de strings.Existem outras maneiras de criar um vetor de strings. Muitos programas bifurcam e executam seus próprios subprocessos com invocações de comando predeterminadas - nesse caso, nunca existe uma "linha de comando". Da mesma forma, um shell gráfico (desktop) pode iniciar um processo quando um usuário arrasta um ícone de arquivo e o solta em um widget de comando - novamente, não há linha de texto para ter caracteres "entre" argumentos.
No que diz respeito ao comando invocado, o que acontece em um shell ou outro processo pai/precursor é privado e oculto - vemos apenas a matriz de strings que o padrão C especifica que
main()
pode aceitar.Não, isso não é possível, a menos que os espaços façam parte de um argumento.
O comando acessa os argumentos individuais de uma matriz (em uma forma ou outra, dependendo da linguagem de programação) e a linha de comando real pode ser salva em um arquivo de histórico (se digitado em um prompt interativo em um shell que possui arquivos de histórico), mas é nunca passou para o comando de nenhuma forma.
Todos os comandos no Unix são no final executados por uma das
exec()
famílias de funções. Eles recebem o nome do comando e uma lista ou matriz de argumentos. Nenhum deles usa uma linha de comando digitada no prompt do shell. Asystem()
função faz, mas seu argumento de string é executado posteriormente porexecve()
, que, novamente, recebe uma matriz de argumentos em vez de uma string de linha de comando.Em geral, não é possível, como várias outras respostas explicadas.
No entanto, shells Unix são programas comuns (e eles estão interpretando a linha de comando e a englobando , ou seja, expandindo o comando antes de fazer
fork
&execve
para ele). Veja esta explicação sobrebash
as operações do shell . Você pode escrever seu próprio shell (ou corrigir algum shell de software livre existente, por exemplo, GNU bash ) e usá-lo como seu shell (ou até mesmo seu shell de login, consulte passwd(5) & shells(5) ).Por exemplo, você pode ter seu próprio programa de shell colocando a linha de comando completa em alguma variável de ambiente (imagine,
MY_COMMAND_LINE
por exemplo) - ou usar qualquer outro tipo de comunicação entre processos para transmitir a linha de comando do shell para o processo filho.Não entendo por que você gostaria de fazer isso, mas pode codificar um shell se comportando dessa maneira (mas recomendo não fazê-lo).
BTW, um programa pode ser iniciado por algum programa que não seja um shell (mas que fork(2) depois execve(2) , ou apenas um
execve
para iniciar um programa em seu processo atual). Nesse caso, não há linha de comando e seu programa pode ser iniciado sem um comando...Observe que você pode ter algum sistema Linux (especializado) sem nenhum shell instalado. Isso é estranho e incomum, mas possível. Você precisará escrever um programa init especializado iniciando outros programas conforme necessário - sem usar nenhum shell, mas fazendo
fork
&execve
chamadas de sistema.Leia também Sistemas Operacionais : Três peças fáceis e não se esqueça que
execve
é praticamente sempre uma chamada do sistema (no Linux, elas estão listadas em syscalls(2) , veja também intro(2) ) que reinicializa o espaço de endereço virtual (e alguns outros coisas) do processo de fazê-lo.Você sempre pode dizer ao seu shell para informar aos aplicativos qual código do shell leva à sua execução. Por exemplo, com
zsh
, passando essa informação na$SHELL_CODE
variável de ambiente usando opreexec()
gancho (printenv
usado como exemplo, você usariagetenv("SHELL_CODE")
em seu programa):Todos aqueles seriam executados
printenv
como:Permitindo
printenv
recuperar o código zsh que leva à execução deprintenv
com esses argumentos. O que você gostaria de fazer com essa informação não está claro para mim.Com
bash
, o recurso mais próximo dezsh
'spreexec()
seria usá-lo$BASH_COMMAND
em umaDEBUG
armadilha, mas observe quebash
ele faz algum nível de reescrita nisso (e, em particular, refatora parte do espaço em branco usado como delimitador) e isso é aplicado a todos (bem, alguns) comandos run, não toda a linha de comando inserida no prompt (consulte também afunctrace
opção).Veja como alguns dos espaços que são delimitadores na sintaxe da linguagem shell foram espremidos em 1 e como nem sempre a linha de comando completa é passada para o comando. Portanto, provavelmente não é útil no seu caso.
Observe que eu não aconselharia fazer esse tipo de coisa, pois você está potencialmente vazando informações confidenciais para todos os comandos, como em:
vazaria esse segredo para ambos
wc
euntrustedcmd
.Claro, você poderia fazer esse tipo de coisa para outras linguagens além do shell. Por exemplo, em C, você poderia usar algumas macros que exportam o código C que executa um comando para o ambiente:
Exemplo:
Veja como alguns espaços foram condensados pelo pré-processador C como no caso do bash. Na maioria, se não em todas as linguagens, a quantidade de espaço usada nos delimitadores não faz diferença, então não é surpresa que o compilador/intérprete tome alguma liberdade com eles aqui.
Vou apenas adicionar o que está faltando nas outras respostas.
Não
Ver outras respostas
Talvez, tipo
Não há nada que possa ser feito no programa, mas há algo que pode ser feito no shell quando você executa o programa.
Você precisa usar aspas. Então, em vez de
você precisa fazer um desses
Isso passará um único argumento para o programa, com todos os espaços. Existe uma diferença entre os dois, o segundo é literal, exatamente a string como aparece (só que
'
deve ser digitado como\'
). A primeira vai interpretar alguns caracteres, mas dividida em vários argumentos. Consulte as citações do shell para obter mais informações. Portanto, não há necessidade de reescrever o shell, os projetistas do shell já pensaram nisso. No entanto, como agora é um argumento, você terá que passar mais no programa.opção 2
Passe os dados via stdin. Esta é a maneira normal de obter grandes quantidades de dados em um comando. por exemplo
ou
./myprog
Tell me what you want to tell me:
aaaa bbb
ctrl-d
(O itálico é a saída do programa)