I was expecting this code to produce
A
A A
A A A A
A A A A A A A A
.....
But instead I get
A
A
A
A
...
Code :
fun() {
var=$1
echo $var #for debugging
var=$var" "$var
fun $var
}
fun "A"
Can you please explain me why and how to get the expected output ?
See above .
CodePudding user response:
The other answers seem to be addressing the infinite recursion but not why the output is not as expected.
The reason you only get A
instead of A A
, A A A A
, etc, is simply that you call fun $var
instead of fun "$var"
.
Because, $var
contains whitespace, if you do not quote it, it gets split (into $1
, $2
, $3
, etc) instead of remaining as a single argument.
CodePudding user response:
Reusing the most of your code as possible (need to add quotes properly):
fun() {
var=$1
echo "$var" # for debugging
var="$var $var" # look the quote style
((${#var} > 50)) && return # avoid infinite recursion
fun "$var"
}
fun "A"
Learn how to quote properly in shell, it's very important :
"Double quote" every literal that contains spaces/metacharacters and every expansion:
"$var"
,"$(command "$var")"
,"${array[@]}"
,"a & b"
. Use'single quotes'
for code or literal$'s: 'Costs $5 US'
,ssh host 'echo "$HOSTNAME"'
. See
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Arguments
http://wiki.bash-hackers.org/syntax/words
when-is-double-quoting-necessary
Output
A
A A
A A A A
A A A A A A A A
A A A A A A A A A A A A A A A A
CodePudding user response:
This function should work for you:
fun() {
[[ ${#1} -gt 20 ]] && { unset var; return; } # bail out & unset var
[[ -z $var ]] && var="$1" # set var first time
echo "$1" # echo passed value
fun "$var $1" # recursive call
}
Test:
fun "A"
A
A A
A A A
A A A A
A A A A A
A A A A A A
A A A A A A A
A A A A A A A A
A A A A A A A A A
A A A A A A A A A A
fun "B"
B
B B
B B B
B B B B
B B B B B
B B B B B B
B B B B B B B
B B B B B B B B
B B B B B B B B B
B B B B B B B B B B
CodePudding user response:
A simplified function definition:
$ fun() { echo "$1"; fun "$1 $1"; }
$ fun "A" | head -6
A
A A
A A A A
A A A A A A A A
A A A A A A A A A A A A A A A A
A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A
NOTES:
- the double quoting is important to insure the entire line of
A's
is treated as a single string - the
head -6
is used here to keep from going into an infinite loop
One idea for limiting the recursion depth would be to keep track of a recursion level, either hardcoded in the function or possibly as an additional argument to the function call; one idea for implementing the latter:
$ fun() { echo "$1"; [[ "$2" -le 1 ]] && return; fun "$1 $1" $(($2-1)) ; }
$ fun "A" 6
A
A A
A A A A
A A A A A A A A
A A A A A A A A A A A A A A A A
A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A
NOTES:
- again, double quoting all variable references is required, especially since we're passing the recursion limit as the 2nd argument (ie, we need to distinguish between the growing line of
A's
and the number in the 'last' position) - OP can decide if additional logic should be added to verify the 2nd argument is in fact a) an integer and b) greater than 0; additional logic could use a default if the 2nd argument is not provided (eg,
${2:-4}
==> default 1st call to using4
) - with some additional coding the recursion limit could be passed as the 1st argument