¿Cuándo debo usar la redirección de entrada?

21

Usé los siguientes dos comandos para producir los mismos resultados:

[root@localhost ~]# grep line comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

[root@localhost ~]# grep line <comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

¿Podría alguien explicarme cualquier pros / contras si alguno de estos 2 enfoques se superponen?

Ankit
fuente

Respuestas:

28

Desde la man greppágina (en Debian):

DESCRIPCIÓN

   grep  searches the named input FILEs (or standard input if no files are
   named, or if a single hyphen-minus (-) is given as file name) for lines
   containing  a  match to the given PATTERN.  By default, grep prints the
   matching lines.

En el primer caso, grepabre el archivo; en el segundo, el shell abre el archivo y lo asigna a la entrada estándar de grep, y al grepno pasar ningún argumento de nombre de archivo se asume que necesita grep su entrada estándar.

Pros de 1:

  • grep puede grep más de un archivo¹.
  • greppuede mostrar el nombre del archivo donde se encuentra cada aparición de line.

Pros de 2:

  • Si el archivo no se puede abrir, el shell devuelve un error que incluirá información más relevante (como el número de línea en la secuencia de comandos) y de una manera más consistente (si deja que el shell también abra archivos para otros comandos) que cuando greplo abre Y si el archivo no se puede abrir, grepni siquiera se llama (lo que para algunos comandos, tal vez no grep, puede marcar una gran diferencia).
  • en grep line < in > out, si inno se puede abrir, outno se creará ni truncará.
  • No hay problema con algunos archivos con nombres inusuales (como -o nombres de archivos que comienzan con -) ².
  • cosmético: puede colocarlo en <filecualquier lugar de la línea de comandos para mostrar el flujo de comandos de forma más natural, como <in grep line >outsi lo prefiere.
  • cosmética: con GNU grep, puede elegir qué etiqueta usar delante de la línea correspondiente en lugar de solo el nombre del archivo como en:

    <file grep --label='Found in file at line' -Hn line
    

En términos de rendimiento, si el archivo no se puede abrir, guarda la ejecución de grepcuando usa la redirección, pero de lo contrario grep, no espero mucha diferencia.

Con la redirección, ahorra tener que pasar un argumento adicional grep, hace que grepel análisis de argumentos sea un poco más fácil. Por otro lado, el shell necesitará (al menos) una llamada de sistema adicional al dup2()descriptor de archivo en el descriptor de archivo 0.

En { grep -m1 line; next command; } < file, grep(aquí GNU grep) querrá seek()regresar justo después de la línea coincidente para que next commandvea el resto del archivo (también deberá determinar si el archivo es buscable o no). En otras palabras, la posición dentro de stdin es otra de greplas salidas. Congrep -m1 line file eso, puede optimizar eso, eso es algo menos por lo grepque preocuparse.


Notas

¹ Con zsh, puedes hacer:

grep line < file1 < file2

pero eso es el equivalente de cat file1 file2 | grep line(sin invocar elcat utilidad) y, por lo tanto, es menos eficiente, puede causar confusión si el primer archivo no termina en un carácter de nueva línea y no le permite saber en qué archivo se encuentra el patrón.

² En el caso de ksh93y bash, sin embargo, hay archivos como /dev/tcp/host/port(y /dev/fd/xen algunos sistemas en bash) que, cuando se usan en el destino de redirecciones, el shell intercepta para fines especiales en lugar de abrir realmente el archivo en el sistema de archivos (aunque generalmente, esos archivos no existe en el sistema de archivos). /dev/stdintiene el mismo propósito que el -reconocido grep, pero al menos aquí tiene un espacio de nombres más apropiado (cualquiera puede crear un archivo llamado -en cualquier directorio, mientras que solo los administradores pueden crear un archivo llamado /dev/tcp/host/porty los administradores deberían saberlo mejor).

Stéphane Chazelas
fuente
+1, por la buena explicación. Tengo una duda: en el segundo caso, cuando el shell abre el archivo, ¿pasa el contenido del archivo abierto a la entrada estándar (teclado)? (Me confundí con el término 'entrada estándar de grep').
Ankit
1
@Ankit, stdin es donde las aplicaciones leen su entrada por defecto, el descriptor de archivo 0. Cuando está en un terminal, fd 0 se abre desde la lectura en el dispositivo terminal (algo así como / dev / ttyxx o / dev / pts / n). Así es como terminan obteniendo lo que escribes en el teclado. La redirección de shell del stdin de un comando solo abre el fd 0 a otro archivo antes de ejecutar el comando.
Stéphane Chazelas 01 de
6

La respuesta de StephaneChazelas cubre grep(1), y la mayoría de los comandos de linaje de Unix funcionan de esa manera, pero no todos. Es estándar leer desde la entrada estándar (desde el teclado, desde un archivo redirigido a través de < file, o desde la salida canalizada por otro comando, ejemplo estúpido ls * | grep '^ab*c$'), o desde el archivo (s) dado como argumento, como grep comment file1 file2 file3. Algunos comandos usan la convención de que el archivo nombrado -es una entrada estándar, por lo que puede decir make-middle | cat head - tailque obtenga una secuencia con headlo que gen-middlegenere, seguido detail . Esto es por diseño, para dar flexibilidad en el uso de los comandos.

¿Cual es mejor? Mientras funcione, cmd filees más corto que cmd < file; podría haber una pequeña diferencia en el tiempo entre el shell que hace el archivo frobbing ( <) y el comando que lo hace solo, pero probablemente no se note a menos que no haga nada más durante todo el día. Dependerá de consideraciones como las ventajas mencionadas en la respuesta de Stephane.

vonbrand
fuente
cmd fileNo es más corto que cmd<filesin embargo.
Stéphane Chazelas
Sin embargo, es una pulsación de tecla más corta, suponiendo que necesite presionar Shift para escribir a <.
DopeGhoti