[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: printf %n is not documented
From: |
Emanuele Torre |
Subject: |
Re: printf %n is not documented |
Date: |
Sat, 7 Jan 2023 17:14:48 +0100 |
User-agent: |
Mutt/2.2.9 (2022-11-12) |
On Sat, Jan 07, 2023 at 03:00:58PM +0100, felix wrote:
> strU8DiffLen0() { local _cLen=${#1} LC_ALL=C;return $((${#1}-_cLen));}
Do not use `return' like that.
`return' is used to make functions report an exit status: 0 for success,
non-zero for various kinds of failure, just like executable programs.
The exit status of a program can only be between 0 and 255, and should
only be between 0 and 125 because 126, 127, and values above 128 have special
meaning for the shell's $? special parameter.
Using `return' to return a value instead of reporting an error code, is
just stupid.
But, in your case, your code is just broken.
Since exit statuses can only ever be a number between 0 and 255, if the
value is above 255 (undocumented), `return' will return the value you
passed modulo 255. Definitely not what you want in your case.
bash-5.1$ a () { return 2000; }; a; echo "$?"
208
bash-5.1$ a () { return -2; }; a; echo "$?"
254
bash-5.1$ a () { return -2; }; a; echo "$?"
254
bash-5.1$ a () { return 100000000; }; a; echo "$?"
254
bash-5.1$ a () { return 10020000000004001; }; a; echo "$?"
161
Behaviour may vary in other shells, e.g. in dash, the same commands
result in:
$ a () { return 2000; }; a; echo "$?"
2000
$ a () { return -2; }; a; echo "$?"
dash: 2: return: Illegal number: -2
$ a () { return 100000000; }; a; echo "$?"
100000000
$ a () { return 10020000000004001; }; a; echo "$?"
dash: 4: return: Illegal number: 10020000000004001
To "return" a value, either use a non-local variable e.g.
myfunction ()
{
local length=${#1} bytelength
printf -v _ %s%n "$1" bytelength
ret_myfunction=$(( lenght - bytelength ))
}
myfunction "$string1"
something "$ret_myfunction"
myotherfunction ()
{
local ret_myfunction len1 len2
myfunction "$1"
len1=$ret_myfunction
myfunction "$2"
len2=$ret_myfunction
myfunction "$3"
something "$(( len1 - len2 - ret_myfunction ))"
}
Or output the result to stdout, and make the caller use command
substitution to read it.
myfunction ()
{
local length=${#1} bytelength
printf -v _ %s%n "$1" bytelength
printf %s\\n "$(( lenght - bytelength ))"
}
something "$(myfunction "$ret_myfunction")"
Another less important note:
Using return $((${#1}-_cLen)) is also problematic, because it is
incorrectly and unnecessarily IFS dependent. If IFS contains a number,
the function will break e.g. if the result of the expression is 103 and
IFS=0, that will run return 1 3 throwing a shell error.
If you ever need to return a computed value from a function (rarely if
you are using `return' correctly instead of misusing it as you were
doing), you should use return -- "$(( ${#1} - _cLen ))" .
Hope this helps.
emanuele6