0
case ${1} in
    "pkey") pkey ;;
    "abserver") abserver ;;
    "exitmenu") exitmenu ;;
    "i3-binds") i3-binds ;;
esac

I have this code to call a function in a script based on $1 (passed as an argument to script). Is there a way to simply call the function in question via $1 and remove the need for case statement?

markp-fuso
  • 28,790
  • 4
  • 16
  • 36
  • Just `$1` alone will call the function. – Marco Bonelli Jun 14 '22 at 18:30
  • 1
    `"$1"` -- that's it. Nothing else. @MarcoBonelli, ...but we shouldn't encourage folks to skip the quotes. – Charles Duffy Jun 14 '22 at 18:30
  • @user3483881, ...note that if you want to pass arguments through, you should use `"$@"` instead. – Charles Duffy Jun 14 '22 at 18:31
  • See [propagate all arguments in a bash shell script](https://stackoverflow.com/questions/4824590/propagate-all-arguments-in-a-bash-shell-script) – Charles Duffy Jun 14 '22 at 18:32
  • @CharlesDuffy there can't be functions with whitespaces in the name. Besides, we shouldn't encourage folks to run `"$1"` regardless... – Marco Bonelli Jun 14 '22 at 18:32
  • 1
    @MarcoBonelli, but you _can_ have `IFS=_`, and functions with underscores in the name. Writing code that only works correctly with default configuration (for a value of "configuration" that includes IFS) is not good practice. – Charles Duffy Jun 14 '22 at 18:32
  • 1
    @MarcoBonelli, ...bigger concern with `$1` unquoted is that you get people putting arguments into it, and running into the bugs discussed in [BashFAQ #50](https://mywiki.wooledge.org/BashFAQ/050). Using `"$1"` prevents that abuse. – Charles Duffy Jun 14 '22 at 18:35

2 Answers2

2

I would use this to validate the parameter:

case $1 in
    pkey|abserver|exitmenu|i3-binds) "$@" ;;
    *) echo "Unknown function: $1" >&2 ;;
esac

I used "$@" to also pass the other parameters as arguments to the function.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
0

script.sh

#!/bin/bash

func1(){ echo "${FUNCNAME[0]} executed with arg1: $1"; }
func2(){ echo "${FUNCNAME[0]} executed with args: $@"; }
func3(){ echo "${FUNCNAME[0]} executed with arg2: $2"; }
[[ $(type -t "$1") == "function" ]] && "$@"||{ echo "error: '$1' undefined function"; exit 1; }

Test

$ ./script.sh func1 "1 2 3" a b
func1 executed with arg1: 1 2 3
$ ./script.sh func2 "1 2 3" a b
func2 executed with args: 1 2 3 a b
$ ./script.sh func3 "1 2 3" a b
func3 executed with arg2: a
$ ./script.sh foo "1 2 3" a b
error: 'foo' undefined function
$ ./script.sh
error: '' undefined function
ufopilot
  • 3,269
  • 2
  • 10
  • 12