Qual è la differenza tra STDIN e gli argomenti passati al comando?


16

Potrei usare entrambi i moduli per eseguire il catmetodo:

cat file_name
cat < file_name

Il risultato è lo stesso

Quindi voglio eseguire mannel formato distdin

man < file_name

Mentre file_namecontiene:

# file_name
cat

Ma si apre What manual page do you want?invece di eseguire man cat.

Voglio sapere perché catpotrebbe accettare stdincome argomenti ma mannon può. E qual è la differenza tra gli argomenti della riga di comando e stdin?

Risposte:


21

La tua domanda è strettamente correlata al modo in cui la shell che stai utilizzando analizza l'input dell'utente sulla riga di comando.

Se la prima parola nella riga di comando è un programma, situato in una cartella speciale (definita principalmente da PATH) e non vengono dati più caratteri speciali (dipende dalla shell che si sta utilizzando), tutte le parole successive separate da spazi o tab vengono passate a il programma in una forma speciale, cioè un array. Con ogni parola come un elemento nell'array.

Come il programma, che si intende invocare, interpreta gli argomenti (situati nella matrice) dipende da come è programmato. Ci sono alcuni quasi standard su come dovrebbe apparire la sintassi degli argomenti, ma in generale il programmatore è completamente libero. Quindi il primo argomento può essere interpretato come il nome di un file o qualunque cosa il programmatore pensi al momento in cui ha scritto il programma.

Nel caso in cui si aggiunga il carattere speciale <o >alla riga di comando, la shell non aggiunge <e >né le parole successive all'array che verrà passato al programma. Con <o >dato la shell inizia a fare cose fantasiose, supportate dal kernel sottostante ( piping parole chiave ). Per comprendere quello che sta succedendo è necessario capire che cosa STDINe STDOUT(poiché non è immediatamente legato i tralascio STDERR) sono.

Tutto ciò che vedi sul tuo terminale (nella maggior parte dei casi una parte del tuo display) è scritto dalla shell o da qualsiasi altro programma che hai invocato in precedenza in un file speciale (in unix tutto è un file ). Questo file ha un ID speciale e viene chiamato STDOUT. Se un programma vuole leggere i dati dalla tastiera, non esegue il polling della tastiera direttamente (almeno nella maggior parte dei casi) ma legge da un file speciale chiamato STDIN. Internamente questo file è collegato al dispositivo di input standard, nella maggior parte dei casi alla tastiera.

Se la shell legge <o >in una riga di comando analizzata, manipola STDINo STDOUTin un tipo particolare per il tempo in cui il programma corrispondente è in esecuzione. STDINe STDOUTnon puntano più al terminale o al dispositivo di input standard ma piuttosto al nome del file successivo sulla riga di comando.

Nel caso delle due linee

cat file_name
cat < file_name

il comportamento osservato è identico perché lo sviluppatore corrispondente fa catleggere STDINo leggere i dati dal file, il cui nome è dato come primo argomento della riga di comando (che è il primo elemento dell'array a cui passa la shell cat). Successivamente catscrive l'intero contenuto di file_nameo STDINsul terminale poiché non istruiamo la shell a manipolare STDOUT. Ricorda che nella seconda riga la tua shell manipola STDINin questo modo, che non punta più al tuo dispositivo di input standard ma punta a un file chiamato file_namenella tua directory di lavoro corrente.

Nell'altro caso della linea

man < file_name

mannon ha lo scopo di leggere nulla STDINse viene chiamato senza argomenti, ad esempio un array vuoto. Quindi la linea

man < file_name

è uguale a

man

Ad esempio manleggerà qualcosa da STDINanche se passi -l -a man. Con questa opzione fornita nella riga di comando è possibile visualizzare il contenuto di tutto ciò che viene manletto STDINsul terminale. Così

man -l - < file_name

funzionerebbe anche (ma attenzione mannon è solo un cercapersone ma analizza anche l'input del file e quindi il contenuto del file e il contenuto visualizzato potrebbero differire).

Quindi STDIN, come STDOUTe gli argomenti della riga di comando vengono interpretati dipende tutto dallo sviluppatore corrispondente.

Spero che la mia risposta possa chiarire le cose.


Grazie per questa spiegazione dettagliata. Per i tuoi ultimi paragrafi, hai citato l'uso man -l - < file_nameper rendere gli maninterpreti STDINcome argomenti, ma non riesce nel mio sistema con STDERR:man -l - < tee man: invalid option -- l man, version 1.6c
steveyang

Prego. Ma non ho menzionato che almeno la mia versione di man( man-db ) legge argomenti STDINcon gli argomenti dati -lseguiti da -. Interpreta semplicemente i dati STDINcome una pagina man. Per spiegazioni più dettagliate sugli argomenti validi e su come vengono interpretati, è necessario consultare la pagina man del relativo programma. Nel tuo caso consultare man man. Forse c'è un'opzione simile per il tuo man. Se vuoi leggere gli argomenti della riga di comando per un programma specifico da STDIN xargs(come menzionato sopra) è la strada da percorrere.
user1146332

Io man mane trovo quello nel mio sistema operativo non lo supporta. Comunque, grazie per questa dichiarazione di questi due concetti per me.
Steveyang,

Ho modificato la tua risposta in modo che contenga collegamenti effettivamente utili anziché lmgtfy. Pubblicare link lmgtfy è 1) maleducato, 2) inutile e 3) molto malvisto sui siti SE. O fornire un collegamento o no, ma se si sceglie di farlo, fornire un collegamento a informazioni effettive e non a un modo sarcastico di mostrare a qualcuno come trovarle.
terdon

12

Sono completamente diversi. Gli argomenti della riga di comando vengono passati al programma in un array e può fare ciò che vuole con loro; stdin è un flusso di input dal quale il programma deve richiedere dati. I programmi che elaborano i file spesso scelgono di supportare entrambi, ma devono farlo manualmente: controllano se un nome di file è stato passato come argomento della riga di comando e in caso contrario leggono invece da stdin

Sembra che ti aspetti mandi leggere stdin per trovare la pagina man che dovrebbe mostrare, il che sarebbe un comportamento davvero strano; quando lo useresti mai? Il fatto che catmostra il suo stdin è un artefatto del fatto che non fa nient'altro; Non penso che nessun altro strumento funzioni in questo modo. Ad esempio, greppuò prendere un nome file o leggere stdin, ma elabora i dati stdin, non legge un nome file stdine quindi lo apre

Se hai davvero bisogno di questo comportamento, potresti usare xargs, che converte un file in argomenti della riga di comando:

$ xargs man < file_name

O semplicemente incorporare una catchiamata nella manchiamata:

$ man $(cat file_name)

In bash, puoi usare man $(<file_name).
Giordania,

Ri: "Non credo che nessun altro strumento funzioni in questo modo" - Perl (<>)in un ciclo farà STDINo argomenti da riga di comando come nomi di file ...
Aaron D. Marasco il

@ AaronD.Marasco Volevo dire che nessuno strumento prende un argomento o legge un nome file da stdin e legge l'argomento da quel file
Michael Mrozek

@MichaelMrozek Grazie per questo chiarimento. Lo scopo che ho usato man < file_nameè di aiutarmi a capire questi due concetti. Leggendo la spiegazione, l'implementazione è decisa dall'autore del comando. Quindi, se ho ragione, l' findargomento accetta piuttosto elabora STDIN?
Steveyang,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.