Soy consciente de la utilidad source
(también conocida como .
), que tomará el contenido de un archivo y lo ejecutará dentro del shell actual.
Ahora, estoy transformando texto en comandos de shell y luego ejecutándolos, de la siguiente manera:
$ ls | sed ... | sh
ls
es solo un ejemplo aleatorio, el texto original puede ser cualquier cosa. sed
también, solo un ejemplo para transformar texto. Lo interesante es sh
. Canalizo lo que sea que llegue sh
y lo ejecuta.
Mi problema es que eso significa iniciar un nuevo sub shell. Prefiero que los comandos se ejecuten dentro de mi shell actual. Como podría hacer con source some-file
, si tuviera los comandos en un archivo de texto.
No quiero crear un archivo temporal porque se siente sucio.
Alternativamente, me gustaría iniciar mi sub shell con exactamente las mismas características que mi shell actual.
actualizar
Ok, las soluciones que usan comillas invertidas ciertamente funcionan, pero a menudo necesito hacer esto mientras reviso y cambio la salida, así que preferiría si hubiera una manera de canalizar el resultado a algo al final.
triste actualización
Ah, la /dev/stdin
cosa se veía tan bonita, pero, en un caso más complejo, no funcionó.
Entonces, tengo esto:
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/git mv -f $1 $2.doc/i' | source /dev/stdin
Lo que garantiza que todos los .doc
archivos tengan su extensión en minúsculas.
Y que, dicho sea de paso, se puede manejar xargs
, pero eso es más allá del punto.
find . -type f -iname '*.doc' | ack -v '\.doc$' | perl -pe 's/^((.*)\.doc)$/$1 $2.doc/i' | xargs -L1 git mv
Entonces, cuando ejecuto el primero, saldrá de inmediato, no pasa nada.
Respuestas:
$ ls | sed ... | source /dev/stdin
ACTUALIZACIÓN: Esto funciona en bash 4.0, así como en tcsh y dash (si cambia
source
a.
). Aparentemente, esto tenía errores en bash 3.2. De las notas de la versión de bash 4.0 :fuente
eval "$(sed ...)"
enfoque, pero gracias por el aviso de error 3.2.El
eval
comando existe para este mismo propósito.eval "$( ls | sed... )"
Más del manual de bash :
fuente
eval "$( ssh remote-host 'cat ~/.bash_profile' )"
Tenga en cuenta que de hecho estoy usando bash 3.2.Vaya, sé que esta es una pregunta antigua, pero recientemente me encontré con el mismo problema exacto (así es como llegué aquí).
De todos modos, no me gusta la
source /dev/stdin
respuesta, pero creo que encontré una mejor. En realidad, es engañosamente simple:echo ls -la | xargs xargs
Bien, ¿verdad? En realidad, esto todavía no hace lo que quieres, porque si tienes varias líneas, las concatena en un solo comando en lugar de ejecutar cada comando por separado. Entonces la solución que encontré es:
la
-L 1
opción significa que usa (como máximo) 1 línea por ejecución de comando. Nota: si su línea termina con un espacio al final, ¡se concatenará con la siguiente línea! Así que asegúrese de que cada línea termine con un no espacio.Finalmente, puedes hacer
para ver qué comandos se ejecutan (-t es detallado).
¡Espero que alguien lea esto!
fuente
Intente usar la sustitución de procesos , que reemplaza la salida de un comando con un archivo temporal que luego se puede obtener:
source <(echo id)
fuente
echo <(echo id)
dando la salida/dev/fd/12
(12 es un ejemplo)cat <(echo id)
, dando la salidaid
y luegosource <(echo id)
dando la misma salida que simplemente escribiendoid
(...)
redirigida?Creo que esta es "la respuesta correcta" a la pregunta:
ls | sed ... | while read line; do $line; done
Es decir, se puede canalizar en un
while
bucle; elread
comando comando toma una línea de sustdin
y la asigna a la variable$line
.$line
luego se convierte en el comando ejecutado dentro del ciclo; y continúa hasta que no haya más líneas en su entrada.Esto todavía no funcionará con algunas estructuras de control (como otro bucle), pero encaja perfectamente en este caso.
fuente
En cierto modo me siento como
ls | sed ... | source -
iba a ser más bonita, pero por desgraciasource
no entiende-
para significarstdin
.fuente
Creo que su solución es la sustitución de comandos con comillas inversas: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html
Ver sección 3.4.5
fuente
$( )
sintaxis puede ser la preferida. 'LasPara usar la solución de mark4o en bash 3.2 (macos), se puede usar una cadena aquí en lugar de tuberías como en este ejemplo:
. /dev/stdin <<< "$(grep '^alias' ~/.profile)"
fuente
¿Por qué no usar
source
entonces?$ ls | sed ... > out.sh ; source out.sh
fuente