/ bin / sh fuente de stdin (de otro programa) no archivo

14

Un poco complicado para nombrar esto ...

Básicamente tengo un programa que cuando se ejecuta imprime en STDOUT un conjunto de variables de shell:

$ ./settings
SETTING_ONE="this is setting one"
SETTING_TWO="This is the second setting"
ANOTHER_SETTING="This is another setting".

Quiero ejecutar esto desde un script de shell como si se estuviera evaluando el STDOUT source.

Me gustaría hacer algo como ...

source `./settings`

... pero por supuesto eso no funciona.

Sé que podría hacer:

./settings >/tmp/file
source /tmp/file

pero realmente no quiero hacer eso.

¿Alguna pista?

Majenko
fuente

Respuestas:

16

Puedes usar eval:

eval "$(./settings)"

eval "`./settings`"
Keith
fuente
Lo siento, debería haber mencionado, es / bin / sh no bash. $ () no funciona. He actualizado la pregunta.
Majenko
@ Matt: Bueno, sh es bash en la mayoría de los sistemas. A menos que, por supuesto, se refiera a las versiones recientes de Ubuntu, donde se ha reemplazado con guión.
Hola71
@ Matt: en ese caso, los backticks deberían funcionar. Pero también debería agregar la versión exacta de sh: podría ser un enlace simbólico a dash, ash, busybox ... No he visto una copia de "la verdadera 'sh'" en vivo.
user1686
1
@Matt: Entonces tienes un ... sistema interesante allí. Especialmente porque casi todas las variaciones "sh" son compatibles $( ), comenzando con el shell de Almquist en 4.3BSD , y también es POSIX. (Nota: sin discutir, solo curioso.)
usuario1686
$ () existe, simplemente no funciona así en esta circunstancia. FreeBSD 8.2's / bin / sh
Majenko
15

En los sistemas donde /dev/fdestá disponible, bash admite la sustitución de procesos:

source <(./settings)

Aquí, <( )se expandirá a una ruta asignada automáticamente bajo la /dev/fd/...cual ./settingsse puede leer la salida de .

usuario1686
fuente
1
En el manual de bash, esto se llama "sustitución de proceso".
Glenn Jackman
6
declare `./settings`

O por supuesto ...

export `./settings`

Pruébalo por supuesto ...

export `echo -e "asdf=test\nqwerty=dvorak"` ; echo $asdf $qwerty

Manejo de espacios en blanco:

eval export `./settings`
Hola71
fuente
¡Ajá, el exporttruco funciona! Gracias
Majenko
Ahora, ¿cómo puedo manejar espacios en un valor?
Majenko
@Matt: no puedo usar backticks en los comentarios, así que por favor vea la respuesta editada.
user1686
@grawity: Sí, puedes ...a backtick --> ` <-- and here's another one --> ` <--
Hola71
2

source /dev/stdin < ./settings

Sin embargo, creo que / dev / stdin es una cosa única de Linux.

LawrenceC
fuente
que intenta obtener el contenido de la configuración. Incluso con './settings' falla con './settings': Ambiguous ('= backtick)
Majenko
/dev/stdintambién funciona en BSD y Cygwin.
user1686
1
Usando |, sin embargo, está no va a funcionar (al menos no exactamente), debido a que ambos lados de la tubería son subprocesos separados, de modo comandos de origen no afectarían a la shell actual.
user1686
1
editado para reflejar eso.
LawrenceC
1
Me gusta este /dev/stdintruco, pero lo que hace su respuesta es, de hecho, equivalente a un plano source ./settingssin ejecutarlo. Se podría utilizar un documento interno para superar esto: source /dev/stdin <<EOF \n $(./settings) \n EOF.
tlwhitec
0

Quería proporcionar otra perspectiva aquí, ya que las otras respuestas crean archivos y no extraen directamente de stdin. Tengo algunas compilaciones que necesitan enviar información del entorno preparada a varios scripts. Lo que estoy haciendo es preparar un montón de asignaciones de variables compatibles con Bash en una cadena:

Var1="Foo"
Var2="Bar"
Var3="Baz"

Cuando me estoy preparando para ejecutar el script, codifico base64 la cadena multilínea anterior y la canalizo en mi script de shell:

echo base64EncodedParameters | build.sh

En build.sh leí de stdin, decodifica base64 y evalué el resultado.

params=""
while read line; do params="${params}${line}"; done
eval `echo $params | base64 -D`

echo "Hello ${Var1} ${Var2}"
Jay Proulx
fuente