¿Hay alguna diferencia entre read, head -1 y sed 1q?

Los siguientes commands parecen ser más o less equivalentes:

read varname varname=$(head -1) varname=$(sed 1q) 

Una diferencia es que read es un shell incorporado mientras que head y sed no lo son.

Además de eso, ¿hay alguna diferencia en el comportamiento entre los tres?

Mi motivación es comprender mejor los matices de la shell y las utilidades key como head,sed . Por ejemplo, si usar head es un reemploop fácil para read , ¿por qué la read existe como un builtin?

Ni la eficiencia ni la construcción son la mayor diferencia. Todos ellos devolverán diferentes resultados para cierta input.

  • head -n1 proporcionará una nueva línea final solo si la input tiene uno.

  • sed 1q siempre proporcionará una línea nueva posterior, pero de lo contrario conservará la input.

  • read nunca proporcionará una nueva línea final e interpretará secuencias de barra invertida.

Además, read tiene opciones adicionales, como split, times de espera e historial de inputs, algunas de las cuales son estándar y otras varían entre shells.

Por un lado, puede analizar el text con la lectura, no solo tomar una línea completa

 echo "foo:bar:baz" | { IFS=: read one two three echo $two } 

Builtins están presentes como una forma de hacer que el sistema llame más rápido. Entonces, creo que el command de read está presente como un sistema integrado para ser más eficiente.

Citando desde aquí ,

Estos commands integrados son parte del shell y se implementan como parte del código fuente del shell. El intérprete de commands reconoce que el command que se le solicitó ejecutar era uno de sus commands incorporados, y realiza esa acción por sí mismo, sin llamar a un ejecutable por separado. Diferentes shells tienen diferentes builtins, aunque habrá una gran cantidad de superposition en el set básico.

Ahora, me gustaría que lo experimente usted mismo, para que pueda entender por qué la read está presente como un shell incorporado.

Normalmente, no strace hacer strace en shell builtins. Sin embargo, hay una solución alternativa para esto también. Esto se explica muy bien en esta respuesta .

  1. En el primer shell, ejecute el command como stty -echo .
  2. Abra otro shell y ejecute el command como cat | strace bash > /dev/null cat | strace bash > /dev/null .
  3. Ahora, el intérprete de commands esperará a que el usuario escriba los commands y cuando el usuario escriba los commands, también podrá ver lo que sucede en el nivel del sistema.
  4. Cuando da los 3 commands anteriores, puede ver que la lectura tiene less llamadas al sistema que los 2 commands restantes. No estoy pegando la salida de strace ya que es bastante grande.

Puede usar read varname solo dentro de un script de shell, pero otros dos puede usar sin escribir el script de shell.

Por ejemplo:

Puede usar varname=$(head -1) y varname=$(sed 1q) simplemente como un command en el terminal, pero también debe proporcionar su argumento, es decir, a qué files se refiere la línea superior, es decir varnam=$(head -1 file1) .