¿Puedo llamar a una función de un script de shell desde otro script de shell?


86

Tengo 2 scripts de shell.

El segundo script de shell contiene las siguientes funciones second.sh

func1 
func2

El first.sh llamará al segundo script de shell con algunos parámetros y llamará a func1 y func2 con algunos otros parámetros específicos de esa función.

Aquí está el ejemplo de lo que estoy hablando.

second.sh

val1=`echo $1`
val2=`echo $2`

function func1 {

fun=`echo $1`
book=`echo $2`

}

function func2 {

fun2=`echo $1`
book2=`echo $2`


}

first.sh

second.sh cricket football

func1 love horror
func2 ball mystery

¿Cómo puedo lograrlo?



3
v=$(echo $1)es completamente redundante. Solo escribe fun2=$1. La única diferencia es que $()(o las comillas inversas) eliminarán las nuevas líneas finales.
William Pursell

1
Dado que no hay nada especial en llamar a una función desde un script de shell en lugar de la línea de comandos, esta pregunta se puede reducir a "¿Cómo llamar a una función bash?"
Tom Russell

Respuestas:


145

Refactorice su second.shscript de esta manera:

function func1 {
   fun=$1
   book=$2
   printf "fun=%s,book=%s\n" "${fun}" "${book}"
}

function func2 {
   fun2=$1
   book2=$2
   printf "fun2=%s,book2=%s\n" "${fun2}" "${book2}"
}

Y luego llame a estas funciones desde un script first.shcomo este:

source ./second.sh
func1 love horror
func2 ball mystery

SALIDA:

fun=love,book=horror
fun2=ball,book2=mystery

12
Para evitar efectos secundarios involuntarios, tenga en cuenta que el sourcecomando ejecutará el script pasado como argumento.
dvlcube

43

No puede llamar directamente a una función en otro script de shell.

Puede mover las definiciones de sus funciones a un archivo separado y luego cargarlas en su script usando el .comando, así:

. /path/to/functions.sh

Esto se interpretará functions.shcomo si su contenido estuviera realmente presente en su archivo en este momento. Este es un mecanismo común para implementar bibliotecas compartidas de funciones de shell.


3
¿No es lo mismo que la respuesta aceptada, ya que .es un alias para source?
ajsharma

9
Bueno, respondí primero, así que técnicamente la respuesta aceptada es la misma que esta :). Además, aunque sourcees un alias de .en muchos shells, no siempre es así. Por ejemplo, el dashpaquete en Debian, que proporciona /bin/sh, no tiene un sourcecomando.
larsks

sourceEl comando no funcionó en Ubuntu @ajsharma. Referencia: comando fuente no encontrado en sh shell
rajeshmag

¿Tan extraño que este comentario no sea votado como el más alto? Esta es la sintaxis correcta #! / Bin / sh y la otra funcionará solo en bash.
xddq

20

El problema

La respuesta actualmente aceptada solo funciona en condiciones importantes. Dado...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

y

/foo/bar/second.sh:

#!/bin/bash

source ./first.sh
func1 World

esto solo funciona si first.shse ejecuta desde el mismo directorio donde first.shse encuentra. Es decir. si la ruta de trabajo actual del shell es /foo, el intento de ejecutar el comando

cd /foo
./bar/second.sh

imprime error:

/foo/bar/second.sh: line 4: func1: command not found

Eso es porque source ./first.shes relativo a la ruta de trabajo actual, no a la ruta del script. Por lo tanto, una solución podría ser utilizar subshell y ejecutar

(cd /foo/bar; ./second.sh)

Solución más genérica

Dado...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

y

/foo/bar/second.sh:

#!/bin/bash

source $(dirname "$0")/first.sh

func1 World

entonces

cd /foo
./bar/second.sh

huellas dactilares

Hello World

Cómo funciona

  • $0 devuelve la ruta relativa o absoluta al script ejecutado
  • dirname devuelve la ruta relativa al directorio, donde existe el script $ 0
  • $( dirname "$0" )el dirname "$0"comando devuelve la ruta relativa al directorio del script ejecutado, que luego se usa como argumento para el sourcecomando
  • en "second.sh", /first.sh simplemente agrega el nombre del script de shell importado
  • source carga el contenido del archivo especificado en el shell actual

0

Si tu defines

    #!/bin/bash
        fun1(){
          echo "Fun1 from file1 $1"
        }
fun1 Hello
. file2 
fun1 Hello
exit 0

en archivo1 (chmod 750 archivo1) y archivo2

   fun1(){
      echo "Fun1 from file2 $1"
    }
    fun2(){
      echo "Fun1 from file1 $1"
    }

y ejecute ./file2 obtendrá Fun1 de file1 Hello Fun1 de file2 Hello Surprise !!! Sobrescribe fun1 en file1 con fun1 de file2 ... Para no hacerlo, debe

declare -f pr_fun1=$fun1
. file2
unset -f fun1
fun1=$pr_fun1
unset -f pr_fun1
fun1 Hello

es guardar su definición anterior para fun1 y restaurarla con el nombre anterior eliminando uno importado no necesario. Cada vez que importa funciones de otro archivo, puede recordar dos aspectos:

  1. puede sobrescribir los existentes con los mismos nombres (si eso es lo que desea, debe conservarlos como se describe anteriormente)
  2. importar todo el contenido del archivo de importación (funciones y variables globales también) ¡Tenga cuidado! Es un procedimiento peligroso

-5
#vi function.sh

#!/bin/bash
f1() {
    echo "Hello $name"
}

f2() {
    echo "Enter your name: "
    read name
    f1
}
f2

#sh function.sh

Aquí la función f2llamará a la funciónf1

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.