Programing

Bash : 함수를 매개 변수로 전달

lottogame 2020. 10. 19. 07:35
반응형

Bash : 함수를 매개 변수로 전달


Bash에서 매개 변수로 함수를 전달해야합니다. 예를 들어, 다음 코드 :

function x() {
  echo "Hello world"
}

function around() {
  echo "before"
  eval $1
  echo "after"
}

around x

다음을 출력해야합니다.

before
Hello world
after

나는 eval그 맥락에서 정확하지 않다는 것을 알고 있지만 그것은 단지 예일뿐입니다. :)

어떤 생각?


함수 이름이나 인수의 평가를 지연시키는 것과 같은 멋진 것이 필요하지 않다면 다음이 필요하지 않습니다 eval.

function x()      { echo "Hello world";          }
function around() { echo before; $1; echo after; }

around x

당신이 원하는 것을합니다. 다음과 같이 함수와 인수를 전달할 수도 있습니다.

function x()      { echo "x(): Passed $1 and $2";  }
function around() { echo before; "$@"; echo after; }

around x 1st 2nd

인쇄물

before
x(): Passed 1st and 2nd
after

질문에 답한 사람은 없다고 생각합니다. 그는 순서대로 문자열을 에코 할 수 있는지 묻지 않았습니다. 오히려 질문의 작성자는 함수 포인터 동작을 시뮬레이션 할 수 있는지 알고 싶어합니다.

내가했던 것과 매우 유사한 몇 가지 답변이 있으며 다른 예를 통해 확장하고 싶습니다.

저자로부터 :

function x() {
  echo "Hello world"
}

function around() {
  echo "before"
  ($1)                   <------ Only change
  echo "after"
}

around x

이를 확장하기 위해 함수 x echo "Hello world : $ 1"함수 실행이 실제로 발생하는시기를 표시합니다. 함수 "x"의 이름 인 문자열을 전달합니다.

function x() {
  echo "Hello world:$1"
}

function around() {
  echo "before"
  ($1 HERE)                   <------ Only change
  echo "after"
}

around x

이를 설명하기 위해 문자열 "x"가 "before"를 에코하는 around () 함수에 전달되고, 인수 "HERE"를 전달하는 x 함수 (변수 $ 1, 주위에 전달 된 첫 번째 매개 변수를 통해)를 호출하고, 마지막으로 이후에 에코됩니다. .

다른 방법으로는 변수를 함수 이름으로 사용하는 방법입니다. 변수는 실제로 함수의 이름 인 문자열을 보유하고 ($ variable arg1 arg2 ...) 인수를 전달하는 함수를 호출합니다. 아래 참조 :

function x(){
    echo $3 $1 $2      <== just rearrange the order of passed params
}

Z="x"        # or just Z=x

($Z  10 20 30)

30 10 20, 여기서 변수 Z에 저장된 "x"라는 함수를 실행하고 매개 변수 10 20 및 30을 전달했습니다.

Above where we reference functions by assigning variable names to the functions so we can use the variable in place of actually knowing the function name (which is similar to what you might do in a very classic function pointer situation in c for generalizing program flow but pre-selecting the function calls you will be making based on command line arguments).

In bash these are not function pointers, but variables that refer to names of functions that you later use.


there's no need to use eval

function x() {
  echo "Hello world"
}

function around() {
  echo "before"
  var=$($1)
  echo "after $var"
}

around x

You can't pass anything to a function other than strings. Process substitutions can sort of fake it. Bash tends to hold open the FIFO until a command its expanded to completes.

Here's a quick silly one

foldl() {
    echo $(($(</dev/stdin)$2))
} < <(tr '\n' "$1" <$3)

# Sum 20 random ints from 0-999
foldl + 0 <(while ((n=RANDOM%999,x++<20)); do echo $n; done)

Functions can be exported, but this isn't as interesting as it first appears. I find it's mainly useful for making debugging functions accessible to scripts or other programs that run scripts.

(
    id() {
        "$@"
    }

    export -f id
    exec bash -c 'echowrap() { echo "$1"; }; id echowrap hi'
)

id still only gets a string that happens to be the name of a function (automatically imported from a serialization in the environment) and its args.

Pumbaa80's comment to another answer is also good (eval $(declare -F "$1")), but its mainly useful for arrays, not functions, since they're always global. If you were to run this within a function all it would do is redefine it, so there's no effect. It can't be used to create closures or partial functions or "function instances" dependent on whatever happens to be bound in the current scope. At best this can be used to store a function definition in a string which gets redefined elsewhere - but those functions also can only be hardcoded unless of course eval is used

Basically Bash can't be used like this.


A better approach is to use local variables in your functions. The problem then becomes how do you get the result to the caller. One mechanism is to use command substitution:

function myfunc()
{
    local  myresult='some value'
    echo "$myresult"
}

result=$(myfunc)   # or result=`myfunc`
echo $result

Here the result is output to the stdout and the caller uses command substitution to capture the value in a variable. The variable can then be used as needed.


You should have something along the lines of:

function around()
{
  echo 'before';
  echo `$1`;
  echo 'after';
}

You can then call around x


eval is likely the only way to accomplish it. The only real downside is the security aspect of it, as you need to make sure that nothing malicious gets passed in and only functions you want to get called will be called (along with checking that it doesn't have nasty characters like ';' in it as well).

So if you're the one calling the code, then eval is likely the only way to do it. Note that there are other forms of eval that would likely work too involving subcommands ($() and ``), but they're not safer and are more expensive.

참고URL : https://stackoverflow.com/questions/5672289/bash-pass-a-function-as-parameter

반응형