how to pass a function with parameters as a parameter? - bash

There are two shell functions like belows
function call_function {
func=$1
desc=$2
log_file=$3
$func >> ${log_file} 2>&1
...
}
function echo_str {
str=$1
echo "$str"
}
How can I pass a shell function with parameters as a parameter?
I tried this:
call_function $( echo_str "test" ) "Echoing something" /var/logs/my_log.log
but only got
command not found
I googled it but nothing helps.
Thanks a lot in advance!

If you want to do this right, reorder your arguments to put the function to call last, and use shift to pop off the other arguments -- which will leave the function to call and its arguments in the "$#" array.
call_function() {
local log_file desc
log_file=$1; shift || return
desc=$1; shift || return
"$#" >>"$log_file" 2>&1
}
echo_str() {
local str
str=$1
echo "$str"
}
# log_file desc func args
call_function myfile.log "a function to echo something" echo_str "string to echo"

call_function $( echo_str "test" ) "Echoing something" /var/logs/my_log.log
This $( echo_str "test" ) call will execute echo_str "test" which will result in test, so call_function will execute:
test >> /var/logs/my_log.log 2>&1
So, you either create a dedicated function to log messages easily to a log file:
log_msg() {
current_date=$(date -u)
echo "[$current_date] $1" >> $2
}
or change call_function as suggested by #Darkman

Related

Interpret return value of bash function

I would like to interpret the return value of the function a in the parent bash.
I want to use return to stop an intermediate script in the parent bash.
In this case it means, that test2 shouldn't be executed.
But it doesn't work.
And I don't want to use exit, because it stops "everything" in the parent process.
Does exist a solution to do that?
Script:
#!/bin/bash
function a {
return 1
}
echo "test1"
a
echo "test2"
Output:
test1
test2
The output should be just
test1
Perhaps you want
#!/bin/bash
a() {
return 1
}
echo "test1"
if ! a; then
echo "test2"
fi
Or for short
echo "test1"
a || echo "test2"
It seems that set -e can do what you want :
#!/usr/bin/env bash
set -e
function a {
return 1
}
echo "test1"
a
echo "test2"
set -e might be a "bad idea" : https://mywiki.wooledge.org/BashFAQ/105#Exercises

concatenate a function with string and execute it

I wanna concatenate a command specified in a function with string and execute it after.
I will simplify my need with an exemple to execute "ls -l -a"
#!/bin/bash
echo -e "specify command"
read command # ls
echo -e "specify argument"
read arg # -l
test () {
$command $arg
}
eval 'test -a'
Except that
Use an array, like this:
args=()
read -r command
args+=( "$command" )
read -r arg
args+=( "$arg" )
"${args[#]}" -a
If you want a function, then you could do this:
run_with_extra_switch () {
"$#" -a
}
run_with_extra_switch "${args[#]}"
#!/bin/bash
echo -e "specify command"
read command # ls
echo -e "specify argument"
read arg # -l
# using variable
fun1 () {
line="$command $arg"
}
# call the function
fun1
# parameter expansion will expand to the command and execute
$line
# or using stdout (overhead)
fun2 () {
echo "$command $arg"
}
# process expansion will execute function in sub-shell and output will be expanded to a command and executed
$(fun2)
It will work for the given question however to understand how it works look at shell expansion and attention must be payed to execute arbitrary commands.
Before to execute the command, it can be prepended by printf '<%s>\n' for example to show what will be executed.

capturing a string return value from one function in bash into another

I am trying to send a string as a return value from a function which is being called by another function in a different file. One sources the other.
The code is, like so:
#####################################################
##filename: conf_abc.menu
#######################################################
#!/bin/bash
source <path>/conf_pqr.menu
function abc () {
var=$(call_pqr)
echo ${var}
}
##Calling function abc
abc
#########################################################
##filename: conf_pqr.menu
########################################################
#!/bin/bash
RET_VAL=""
function get_intf() {
cmd=`some command`
RET_VAL=${cmd}
}
function call_pqr () {
comm=$(array of choices)
for choice in $comm
do
case $choice in
IF)get_intf;
echo "$RET_VAL";;
esac
done
}
I expect to see the choice from the array in "var" of function abc().
But the "echo ${var}" in conf_abc.menu does not print anything.
I run the script by doing:
./conf_abc.menu
What am I doing wrong?
Thanks for the comments. I found that when the return is called from the function, the entire output from echo is captured into the return variable. I then filtered the output using ">&2". I find that I do get the proper return string.
This I found from:
stackoverflow.com/questions/11758368/shell-script-function-return-a-string
I have put in a minimal example here:
##**file: vlan_menu.sh**
#!/bin/bash
source <path>/ifs_menu.sh
function conf_vlan () {
echo "Calling function if_menu" >&2
local output1=$(if_menu);
echo "printing result" >&2
ENET1="${output1}"
echo "ENET1 is= "${ENET1}"" >&2
}
conf_vlan; --> calling the main function
##**file: ifs_menu.sh**
#!/bin/bash
RET_VAL=""
function get_if() {
PI=$1
local var1=$(shell command)
if [ ! -z "${PI}" ]
then
local var2=<do something with var1>
else
local var2=<do something with var1>
fi
local cmd=$(start shell utility)
RET_VAL=${cmd}
}
function if_menu() {
comm=(1 2 3 4 5)
for choice in ${comm}
do
case $choice in
1) echo "IF" >&2;
get_if "";
echo "${RET_VAL}";;
2) echo "SF" >&2;
get_if $1;
echo "${RET_VAL}";;
esac
done
}
After running "vlan_menu.sh" script file, the value of "ENET1" is the same as "RET_VAL" which is what I wanted to see.
-rsmitha.

Substituting variable inside a string stored in array - bash

My strings are stored inside array, a sample string contains a 'variable'.
While iterating over this array, I want to substitute the 'variable' with a 'value'.
This fails for me. I have tried my lot in various ways & googled but could not figure it out
# Array of strings (each string is a command)
clean_aa_commands=(
"sourceanalyzer -b ${FortifyBuildId} -clean"
"cd ${unifiedbuilddir}/AA/AAUI"
"mvn clean"
)
# Functions
function check {
if [ "$?" -ne 0 ]; then
echo "Operation [$1] Unsuccessful!"
else
echo "Operation [$1] Success!"
fi
}
function runcmds {
echo "using $FortifyBuildId *************************"
cmdArr=("${!1}")
for cmd in "${cmdArr[#]}"
do
echo "-->Running [$cmd]"
eval "$cmd"
check "$cmd"
echo ""
echo ""
done
}
# main
FortifyBuildId="$1"
echo "FortifyBuildId is $FortifyBuildId"
unifiedbuilddir=`pwd`
runcmds clean_aa_commands["#"]
How about this
cmds='cmds=( /test/$mydir /test/$test )'
mydir=$(pwd)
test="me"
eval ${cmds}
echo ${cmds[#]}

escaping sh/bash function arguments

I want to submit multiple commands with arguments to shell functions, and thus quote my commands like his:
$ CMD=''\''CMD'\'' '\''ARG1 ARG2 ARG3'\'''
$ echo $CMD
'CMD' 'ARG1 ARG2 ARG3' 'ARG4'
Now when I try to us them in a function like this:
$ function execute { echo "$1"; echo "$2"; echo "$3"; }
I get the result:
$ execute $CMD
'CMD'
'ARG1
ARG2
How can I get to this result:
$ execute $CMD
CMD
ARG1 AGR2 ARG3
Thanks in advance!
PS: I use an unquoting function like:
function unquote { echo "$1" | xargs echo; }
EDIT:
to make my intentions more clear: I want to gradually build up a command that needs arguments with spaces passed to subfunctions:
$ CMD='HOST '\''HOSTNAME'\'' '\''sh SCRIPTNAME'\'' '\''MOVE '\''\'\'''\''/path/to/DIR1'\''\'\'''\'' '\''\'\'''\''/path/to/DIR2'\''\'\'''\'''\'''
$ function execute { echo "$1 : $2 : $3 : $4"; }
$ execute $CMD
HOST : 'HOSTNAME' : 'sh : SCRIPTNAME'
The third arguments breaks unexpected at a space, the quoting is ignored. ??
Use an array and # in double quotes:
function execute () {
echo "$1"
echo "$2"
echo "$3"
}
CMD=('CMD' 'ARG1 ARG2 ARG3' 'ARG4')
execute "${CMD[#]}"
function execute {
while [[ $# > 0 ]]; do
cmd=$(cut -d' ' -f1 <<< $1)
arg=$(sed 's/[^ ]* //' <<< $1)
echo "$cmd receives $arg"
shift
done
}
CMD1="CMD1 ARG11 ARG12 ARG13"
CMD2="CMD2 ARG21 ARG22 ARG23"
execute "$CMD1" "$CMD2"
Gives:
CMD1 receives ARG11 ARG12 ARG13
CMD2 receives ARG21 ARG22 ARG23

Resources