Qual é a diferença entre STDIN e argumentos passados para o comando?

10

Eu poderia usar o formulário para executar o método cat :

cat file_name
cat < file_name

O resultado é o mesmo

Então, quero executar man no formato de stdin

man < file_name

Enquanto file_name contém:

# file_name
cat

Mas aparece What manual page do you want? em vez de executar man cat .

Eu quero saber por que cat poderia aceitar stdin como argumentos, mas man não pode. E qual é a diferença entre os argumentos da linha de comando e stdin ?

    
por steveyang 26.08.2012 / 19:39

2 respostas

15

Sua pergunta está intimamente relacionada a como o shell que você está usando analisa a entrada do usuário na linha de comando.

Se a primeira palavra na linha de comando for um programa, localizado em uma pasta especial (definida principalmente por PATH ) e nenhum caractere especial for fornecido (depende do shell que você está usando), todas as palavras subsequentes serão separadas por espaços ou tabulações são passados para o programa de uma forma especial, isto é, uma matriz. Com cada palavra como um elemento na matriz.

Como o programa, você vai chamar interpreta os argumentos (localizados na matriz) depende de como ele é programado. Existem alguns padrões quase de como a sintaxe dos argumentos deve parecer, mas em geral o programador é totalmente livre. Assim, o primeiro argumento pode ser interpretado como um nome de um arquivo ou qualquer que seja o pensamento do programador no momento em que ele escreveu o programa.

Caso você adicione o caractere especial < ou > à sua linha de comando, o shell não adicionará < e > nem as palavras subsequentes à matriz que será passada para o programa. Com < ou > dado o shell começa a fazer coisas sofisticadas, suportado pelo kernel subjacente (keyword piping ). Para entender o que está acontecendo, você deve entender o que é STDIN e STDOUT (já que não está imediatamente relacionado omitido STDERR ).

Tudo o que você vê no seu terminal (na maioria dos casos, uma parte do seu monitor) é escrito pelo shell ou qualquer outro programa que você tenha chamado anteriormente para um arquivo especial (em unix tudo é um arquivo ). Este arquivo tem um id especial e é chamado de STDOUT . Se um programa desejar ler dados do teclado, ele não pesquisará o teclado diretamente (pelo menos na maioria dos casos), mas lerá de um arquivo especial chamado STDIN . Internamente, este arquivo é conectado ao seu dispositivo de entrada padrão, seu teclado na maioria dos casos.

Se o shell ler < ou > em uma linha de comando analisada, ele manipula STDIN ou STDOUT em um tipo específico durante o tempo em que o programa correspondente está sendo executado. STDIN e STDOUT não apontam para o terminal ou para o dispositivo de entrada padrão, mas sim para o nome de arquivo subseqüente na linha de comando.

No caso das duas linhas

cat file_name
cat < file_name

o comportamento observado é idêntico porque o desenvolvedor correspondente transforma cat em ler dados de STDIN ou ler os dados do arquivo, cujo nome é dado como o primeiro argumento de linha de comando (que é o primeiro elemento no array o shell passa para cat ). Subsequentemente, cat grava todo o conteúdo de file_name ou STDIN no terminal, pois não instruímos o shell a manipular STDOUT . Lembre-se que na segunda linha seu shell manipula STDIN desta forma, que ele não aponta para seu dispositivo de entrada padrão anylonger, mas aponta para um arquivo chamado file_name em seu diretório de trabalho atual.

No outro caso da linha

man < file_name

man não deve ler nada de STDIN se for chamado sem argumento, ou seja, uma matriz vazia. Então a linha

man < file_name

é igual a

man

Por exemplo, man lerá algo de STDIN , também se você passar -l - para man . Com esta opção dada na linha de comando você pode exibir o conteúdo de qualquer coisa manSTDIN no seu terminal. Então

man -l - < file_name

também funcionaria (mas tenha cuidado, man não é apenas um pager, mas também analisa a entrada do arquivo e, portanto, o conteúdo do arquivo e o conteúdo exibido podem ser diferentes).

Então, como STDIN , STDOUT e os argumentos da linha de comando são interpretados, tudo depende do desenvolvedor correspondente.

Espero que minha resposta possa esclarecer as coisas.

    
por 26.08.2012 / 21:30
12

Eles são completamente diferentes. Argumentos de linha de comando são passados para o programa em uma matriz e ele pode fazer o que quiser com eles; stdin é um fluxo de entrada do qual o programa deve solicitar dados. Programas que processam arquivos geralmente escolhem para ambos, mas eles têm que fazê-lo manualmente - eles checam se um nome de arquivo foi passado como um argumento de linha de comando, e se não eles leram de stdin em vez disso

Você parece estar esperando que man leia stdin para encontrar a página de manual que ele deve exibir, o que seria um comportamento realmente estranho; quando você usaria isso? O fato de cat exibir sua stdin é um artefato do fato de que não faz mais nada; Eu não acho que qualquer outra ferramenta funcione dessa maneira. Por exemplo, grep pode pegar um nome de arquivo ou ler stdin , mas processa os dados em stdin , não lê um nome de arquivo de stdin e, em seguida, o abre

Se você realmente precisar desse comportamento, poderá usar xargs , que converte um arquivo em argumentos de linha de comando:

$ xargs man < file_name

Ou apenas incorpore uma chamada cat na chamada man :

$ man $(cat file_name)
    
por 26.08.2012 / 20:09