¿Cuál es la diferencia entre <<
, <<<
y < <
en bash?
command-line
bash
redirect
Searene
fuente
fuente
Respuestas:
Aquí documenta
<<
que se conoce comohere-document
estructura. Dejas que el programa sepa cuál será el texto final, y cada vez que se ve ese delimitador, el programa leerá todo lo que le has dado al programa como entrada y realizará una tarea sobre él.Esto es lo que quiero decir:
En este ejemplo, le decimos al
wc
programa que espere laEOF
cadena, luego escriba cinco palabras y luego escribaEOF
para indicar que hemos terminado de dar entrada. En efecto, es similar a correrwc
solo, escribir palabras y luego presionarCtrlDEn bash, estos se implementan a través de archivos temporales, generalmente en forma
/tmp/sh-thd.<random string>
, mientras que en el tablero se implementan como canalizaciones anónimas. Esto se puede observar a través de las llamadas del sistema de seguimiento constrace
comando. Reemplacebash
consh
para ver cómo se/bin/sh
realiza esta redirección.Aquí cadena
<<<
que se conoce comohere-string
. En lugar de escribir texto, le da una cadena de texto prefabricada a un programa. Por ejemplo, con el programabc
que podemos hacerbc <<< 5*4
para obtener resultados para ese caso específico, no es necesario ejecutar bc de forma interactiva.Las cadenas aquí en bash se implementan a través de archivos temporales, generalmente en el formato
/tmp/sh-thd.<random string>
, que luego se desvinculan, lo que hace que ocupen temporalmente un espacio de memoria pero no se muestren en la lista de/tmp
entradas de directorio, y efectivamente existan como archivos anónimos, que aún pueden se hará referencia a través del descriptor de archivo por el propio shell, y el descriptor de archivo será heredado por el comando y luego duplicado en el descriptor de archivo 0 (stdin) a través de ladup2()
función. Esto se puede observar a través deY a través de rastreo de llamadas al sistema (salida acortada para facilitar la lectura; observe cómo se abre el archivo temporal como FD 3, los datos grabados en ellos, entonces se vuelve a abrir con
O_RDONLY
marcar como fd 4 y posteriores no enlazado, a continuación,dup2()
en fd 0, que se hereda por lacat
tarde ):Opinión: potencialmente porque las cadenas aquí utilizan archivos de texto temporales, es la posible razón por la cual las cadenas aquí siempre insertan una nueva línea final, ya que el archivo de texto por definición POSIX debe tener líneas que terminen en un carácter de nueva línea.
Proceso de sustitución
Como tldp.org explica ,
En efecto, esto es similar a la canalización estándar de un comando al otro, por ejemplo
echo foobar barfoo | wc
. Pero aviso: en la página de manual de bash tenga verá que se denota como<(list)
. Entonces, básicamente, puede redirigir la salida de múltiples (!) Comandos.Nota: técnicamente cuando dice
< <
que no se refiere a una cosa, sino a dos redirecciones con una sola<
redirección de salida y de proceso<( . . .)
.¿Qué sucede si solo procesamos la sustitución?
Como puede ver, el shell crea un descriptor de archivo temporal
/dev/fd/63
donde va la salida (que según la respuesta de Gilles , es una tubería anónima). Eso significa<
que redirige ese descriptor de archivo como entrada en un comando.Entonces, un ejemplo muy simple sería hacer la sustitución del proceso de salida de dos comandos echo en wc:
Así que aquí hacemos que Shell cree un descriptor de archivo para toda la salida que ocurre en el paréntesis y lo redirige como entrada a
wc
. Como se esperaba, wc recibe esa secuencia de dos comandos de eco, que por sí solo generaría dos líneas, cada una con una palabra, y apropiadamente tenemos 2 palabras, 2 líneas y 6 caracteres más dos líneas nuevas contadas.Nota al margen : La sustitución del proceso puede denominarse bashism (un comando o estructura que se puede usar en shells avanzados
bash
, pero no especificado por POSIX), pero se implementóksh
antes de la existencia de bash como la página de manual de ksh y esta respuesta sugiere. Conchas comotcsh
ymksh
sin embargo no tienen sustitución proceso. Entonces, ¿cómo podríamos redirigir la salida de múltiples comandos a otro comando sin sustitución del proceso? Agrupación más tuberías!Efectivamente, esto es lo mismo que el ejemplo anterior. Sin embargo, esto es diferente bajo el capó de la sustitución del proceso, ya que hacemos stdout de todo el subshell y stdin de
wc
enlazado con la tubería . Por otro lado, la sustitución del proceso hace que un comando lea un descriptor de archivo temporal.Entonces, si podemos agrupar con tuberías, ¿por qué necesitamos la sustitución de procesos? Porque a veces no podemos usar tuberías. Considere el siguiente ejemplo: comparar las salidas de dos comandos con
diff
(que necesita dos archivos, y en este caso le damos dos descriptores de archivo)fuente
< <
se usa cuando uno está recibiendo stdin de una sustitución de proceso . Tal orden podría ser:cmd1 < <(cmd2)
. Por ejemplo,wc < <(date)
< <
no es una cosa en sí misma, en el caso de la sustitución del proceso es solo<
seguido de otra cosa con la que comienza<
<<<
primero fue implementado por el puerto Unix de Plan 9 rc shell y luego adoptado por zsh, bash y ksh93. Entonces no lo llamaría bashism.echo 'foo' | read; echo ${REPLY}
será no regresarfoo
, porqueread
se inicia en una sub-shell - tuberías inicia un sub-shell. Sin embargo,read < <(echo 'foo'); echo ${REPLY}
regresa correctamentefoo
, porque no hay sub-shell.< <
es un error de sintaxis:< <()
es la sustitución del proceso (<()
) combinada con la redirección (<
):Un ejemplo artificial:
Con la sustitución del proceso, la ruta al descriptor de archivo se usa como un nombre de archivo. En caso de que no desee (o no pueda) usar un nombre de archivo directamente, combina la sustitución del proceso con la redirección.
Para ser claros, no hay
< <
operador.fuente
<()
le da un aspecto de nombre de archivo, por lo que es más útil en general:< <()
está reemplazando el stdin donde podría no ser necesario. Enwc
, este último pasa a ser más útil. Podría ser menos útil en otros lugares< <
es un error de sintaxis, probablemente quiere decircommand1 < <( command2 )
que es una simple redirección de entrada seguida de una sustitución de proceso y es muy similar pero no equivalente a:La diferencia asumiendo que está ejecutando
bash
secommand1
ejecuta en un subshell en el segundo caso mientras se ejecuta en el shell actual en el primero. Eso significa que las variables establecidascommand1
no se perderían con la variante de sustitución del proceso.fuente
< <
dará un error de sintaxis. El uso adecuado es el siguiente:Explicando con la ayuda de ejemplos:
Ejemplo para
< <()
:En el ejemplo anterior, la entrada al bucle while vendrá del
ls
comando que se puede leer línea por línea yecho
editar en el bucle.<()
se usa para la sustitución de procesos.<()
Puede encontrar más información y ejemplos en este enlace:Proceso de sustitución y tubería
fuente