This question already has answers here:
Bash script returning "Not found" error
(2 answers)
Closed 9 years ago.
Hi i'm new to bash scripting but cannot understand why i get the command not found error when i try to assign to a local variable the result of this function call with parameters 20120920 5.
#!/bin/bash
function nDaysAgo () #date # daysago
{
date -d "${1} - ${2} days" +%Y%m%d;
}
so the script name is ndaysago, i'm first invoking the script with . ndaysago and then assigning the value like this:
newdate= nDaysAgo 20120910 5
it prints: 20120905: command not found
Meaning that the date execution is made but then tries to use the output as command, thats not what i would expect.
i have also tried assigning the new value to a variable within the function like so:
#!/bin/bash
function nDaysAgo () #date # daysago
{
var=$(date -d "${1} - ${2} days" +%Y%m%d)
}
but still nothing, mmmmmm
Spaces are not allowed around the = when assigning a variable. To invoke a function you should use the $(...) syntax which is called command substitution.
Change to:
newdate=$(nDaysAgo 20120910 5)
Related
This question already has answers here:
In bash, how to store a return value in a variable?
(8 answers)
Closed 3 years ago.
In a function, I'm trying to extract the process ID from a line of text. Also, I'm trying to return that process ID:
#!/bin/bash
regex="[a-z]* ([0-9]+) .*"
indexRawRow="sahandz 9040 other stuff comes here"
getPidFromRow() {
if [[ $1 =~ $regex ]]
then
pid=${BASH_REMATCH[1]}
else
pid=""
fi
echo "pid is $pid inside function"
return $pid
}
processId=$(getPidFromRow "$indexRawRow")
echo "pid is $processId outside of function"
The output is:
pid is pid is 9040 inside function outside of function
There are a few problems here:
The two echo statements seem interwoven, indicating that the function and the main scope are running in paralell. Is this supposed to happen? Can it be turned off?
The outside scope never gets the value of the process ID. As you can see, it's only printed once. Through testing, I know that it is only the echo inside of the function that is printing the process ID 9040. The outside scope seems to not have gotten the process ID.
What is the reason for these problems?
Your assumptions are convoluted here, what you are seeing in the variable processId at the output of $(..) is the output of the echo statement and not the return-ed value from function.
You simply can't return strings from a function in bash. Just unsigned integer codes from 0-255. If you were to return only the the matched group from the function, leave out the return statement and just print the matched group
getPidFromRow() {
# Your other code here
# ..
printf '%d\n' "$pid"
}
This question already has answers here:
How to define a function on one line
(1 answer)
Define function in unix/linux command line (e.g. BASH)
(5 answers)
Closed 5 years ago.
All I want to do is write and export a shell function without:
1) opening a file
2) editing it
3) saving it
4) running it
I'm aware of the implications... Something like:
$ afunc () { echo "i am awesome" } && export -f afunc
When i call afunc it will print "i am awesome" but if i try to do that I get this situation
$ afunc () { echo "aaa" }
>
Anyway way i can do this dynamically from stdin or something?
This isn't a problem with being inside/outside a script, but a problem in how you're compressing your definition down to a one-liner: You need (but are not including) a semicolon before the closing brace.
The following works:
afunc () { echo "i am awesome"; } && export -f afunc
A hitchhiker, waned by the time a function is taking to complete, wishes to find where a function is located, so that he can observe the function for himself by editting the file location. He does not wish to print the function body to the shell, simply get the path of the script file containing the function. Our hitchhiker only knows the name of his function, which is answer_life.
Imagine he has a function within a file universal-questions.sh, defined like this, the path of which is not known to our hitchhiker:
function answer_life() {
sleep $(date --date='7500000 years' +%s)
echo "42"
}
Another script, called hitchhiker-helper-scripts.sh, is defined below. It has the function above source'd within it (the hitchhiker doesn't understand source either, I guess. Just play ball.):
source "/usr/bin/universal-questions.sh"
function find_life_answer_script() {
# Print the path of the script containing `answer_life`
somecommand "answer_life" # Should output the path of the script containing the function.
}
So this, my intrepid scripter, is where you come in. Can you replace the comment with code in find_life_answer_script that allows our hitchhiker to find where the function is located?
In bash operating in extended debug mode, declare -F will give you the function name, line number, and path (as sourced):
function find_life_answer_script() {
( shopt -s extdebug; declare -F answer_life )
}
Like:
$ find_life_answer_script
answer_life 3 ./universal-questions.sh
Running a sub-shell lets you set extdebug mode without affecting any prior settings.
Your hitchhiker can also try to find the answer this way:
script=$(readlink -f "$0")
sources=$(grep -oP 'source\s+\K[\w\/\.]+' $script)
for s in "${sources[#]}"
do
matches=$(grep 'function\s+answer_life' $s)
if [ -n "${matches[0]}" ]; then
echo "$s: Nothing is here ("
else
echo "$s: Congrats! Here is your answer!"
fi
done
This is for case if debug mode will be unavailable on some planet )
This question already has answers here:
Bash - variable variables [duplicate]
(4 answers)
Dynamic variable names in Bash
(19 answers)
Closed 5 years ago.
From my code below, how to make the value of 'zz' become 500 after replacing 'critical_' with x on variable 'yy'
xab123=500
yy="critical_ab123"
zz=${"${yy//critical_/x}"}
echo $zz
instead the result, there is an error:
line 8: ${"${yy//critical_/x}"}: bad substitution
thanks
adi
May be like this:
xab123=500
yy="critical_ab123"
zz="${yy//critical_/x}"
echo ${!zz}
500
An interesting usage is when you call a bash function, you can use indirection on the parameters passed in. Then, you can nest calls to your indirection function in a nested manner using command substitution.
deref() { echo "${!1}"; }
aa="bb"
bb="cc"
cc="hello"
echo "$(deref aa)" # bb
echo "$(deref "$(deref aa)")" # cc
echo "$(deref "$(deref "$(deref aa)")")" # hello
Here's deref used to solve the OP's problem:
deref() { echo "${!1}"; }
xab123="500"
yy="critical_ab123"
zz="$(deref "${yy//critical_/x}")"
echo "$zz" # Outputs: 500
Applied edits based on #charles-duffy comments:
Disclaimer: reader beware, there are performance impacts to the command substitution used in this approach (FIFO creation, fork() of a subshell, read() and wait().
Quotes were added to protect against lossy expansion, i.e. echo "$zz" is better than echo $zz
Use POSIX-compliant function declaration syntax, i.e. replaced function deref { echo "${!1}" ; } with deref() { echo "${!1}" ; }
Corrected quoting issue for each quoting context
This question already has answers here:
How to determine function name from inside a function
(5 answers)
Closed 5 years ago.
In BASH, is it possible to get the function name in function body? Taking following codes as example, I want to print the function name "Test" in its body, but "$0" seems to refer to the script name instead of the function name. So how to get the function name?
#!/bin/bash
function Test
{
if [ $# -lt 1 ]
then
# how to get the function name here?
echo "$0 num" 1>&2
exit 1
fi
local num="${1}"
echo "${num}"
}
# the correct function
Test 100
# missing argument, the function should exit with error
Test
exit 0
Try ${FUNCNAME[0]}. This array contains the current call stack. To quote the man page:
FUNCNAME
An array variable containing the names of all shell functions
currently in the execution call stack. The element with index 0
is the name of any currently-executing shell function. The bot‐
tom-most element is "main". This variable exists only when a
shell function is executing. Assignments to FUNCNAME have no
effect and return an error status. If FUNCNAME is unset, it
loses its special properties, even if it is subsequently reset.
The name of the function is in ${FUNCNAME[ 0 ]} FUNCNAME is an array containing all the names of the functions in the call stack, so:
$ ./sample
foo
bar
$ cat sample
#!/bin/bash
foo() {
echo ${FUNCNAME[ 0 ]} # prints 'foo'
echo ${FUNCNAME[ 1 ]} # prints 'bar'
}
bar() { foo; }
bar