Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

getopts from within function

32 views
Skip to first unread message

Henryk Nowicki

unread,
Feb 7, 2016, 1:58:18 PM2/7/16
to
Good day!

I have a problem with getopts from within function like this:

function f_randpw {
# local OPTIND "hn:s"
# unset OPTIND
# OPTIND=1
while getopts "hn:s" Option; do
case $Option in
n ) NUMBCHAR=${OPTARG}
;;
s ) SPECCHAR=true
;;
h|* ) echo "usage: $(basename $0) [-s] [-n number]"
return
;;
esac
done
# shift $((OPTIND-1))

if [ "$SPECCHAR" == "true" ]; then
cat /dev/random | tr -cd [:graph:] | fold -w ${NUMBCHAR:-32} | head -1
else
cat /dev/random | tr -cd [:alnum:] | fold -w ${NUMBCHAR:-32} | head -1
fi
}

I also tried commented out strings, but it doesn't work either.

Example:
$f_randpw -n 10
QfBwUfh0O7

$f_randpw
9lzlBmp3L6 <-- It should be 32 characters, not 10

If I run it not as function, but as script, it work OK.
I'am using ksh from OpenBSD 5.8.

Thank you!

Janis Papanagnou

unread,
Feb 7, 2016, 2:45:04 PM2/7/16
to
What version of ksh is that exactly?

I'm using original ksh Version AJM 93u+ 2012-08-01 and your script is
functional here. (I'm just using /dev/urandom instead of /dev/random.)

Janis

>
> Thank you!
>

Janis Papanagnou

unread,
Feb 7, 2016, 3:05:02 PM2/7/16
to
On 07.02.2016 20:44, Janis Papanagnou wrote:
> On 07.02.2016 19:55, Henryk Nowicki wrote:
>> Good day!
>>
>> I have a problem with getopts from within function like this:

Now I see your problem. You are setting a variable NUMBCHAR in the global
scope. If you one called it with an option -n the variable keeps its value
in subsequent calls unless it's redefined again with another -n option.
To fix that it should be sufficient to set NUMBCHAR= at the beginning
of the function. And some more changes suggested below...

>>
>> function f_randpw {

NUMBCHAR=

>> while getopts "hn:s" Option; do
>> case $Option in
>> n ) NUMBCHAR=${OPTARG}
>> ;;
>> s ) SPECCHAR=true
>> ;;
>> h|* ) echo "usage: $(basename $0) [-s] [-n number]"
>> return
>> ;;
>> esac
>> done
>> # shift $((OPTIND-1))
>>
>> if [ "$SPECCHAR" == "true" ]; then

if [[ "$SPECCHAR" == "true" ]]; then

>> cat /dev/random | tr -cd [:graph:] | fold -w ${NUMBCHAR:-32} | head -1

tr -cd '[:graph:]' </dev/random | fold -w "${NUMBCHAR:-32}" | head -1

>> else
>> cat /dev/random | tr -cd [:alnum:] | fold -w ${NUMBCHAR:-32} | head -1

tr -cd '[:alnum:]' </dev/random | fold -w "${NUMBCHAR:-32}" | head -1

Joerg.S...@fokus.fraunhofer.de

unread,
Feb 8, 2016, 11:18:29 AM2/8/16
to
In article <n983um$spm$1...@dont-email.me>,
1) You need to reset OPTIND to 1 before you start another attempt of
option parsing

2) You need to "unset NUMBCHAR" if you like ${NUMBCHAR:-32} to work
the second time where you did not specify the -n argument.

This would of course also apply to SPECCHAR

--
EMail:jo...@schily.net (home) Jörg Schilling D-13353 Berlin
joerg.s...@fokus.fraunhofer.de (work) Blog: http://schily.blogspot.com/
URL: http://cdrecord.org/private/ http://sourceforge.net/projects/schilytools/files/

Janis Papanagnou

unread,
Feb 8, 2016, 11:24:53 AM2/8/16
to
This is not correct. You don't need to rest it in a ksh function; it will
be resetted on every function invocation.

Janis

Joerg.S...@fokus.fraunhofer.de

unread,
Feb 9, 2016, 9:23:51 AM2/9/16
to
In article <n9afgh$k6n$1...@news.m-online.net>,
Janis Papanagnou <janis_pa...@hotmail.com> wrote:

>> 1) You need to reset OPTIND to 1 before you start another attempt of
>> option parsing
>
>This is not correct. You don't need to rest it in a ksh function; it will
>be resetted on every function invocation.

You are mistaken: OPTIND is a normal variable and it cannot be reset
automatically without being in conflict with POSIX.

As a result, you need to manually reset it whenever you start a new option
parsing cycle - you just leave it alone when you loop over calling "getopts"
to parse the options for a single command line invocation.

Janis Papanagnou

unread,
Feb 9, 2016, 11:11:01 AM2/9/16
to
On 09.02.2016 15:23, Joerg.S...@fokus.fraunhofer.de wrote:
> In article <n9afgh$k6n$1...@news.m-online.net>,
> Janis Papanagnou <janis_pa...@hotmail.com> wrote:
>
>>> 1) You need to reset OPTIND to 1 before you start another attempt of
>>> option parsing
>>
>> This is not correct. You don't need to rest it in a ksh function; it will
>> be resetted on every function invocation.
>
> You are mistaken: OPTIND is a normal variable and it cannot be reset
> automatically without being in conflict with POSIX.

You are mistaken. Ksh funktions (which, AFAIR, are not specified by POSIX)
behave exactly that way. You may just try it out. And it's even documented.

Janis

> [...]

Joerg.S...@fokus.fraunhofer.de

unread,
Feb 10, 2016, 6:44:58 AM2/10/16
to
In article <n9d32f$dk5$1...@news.m-online.net>,
Janis Papanagnou <janis_pa...@hotmail.com> wrote:
>On 09.02.2016 15:23, Joerg.S...@fokus.fraunhofer.de wrote:
>> In article <n9afgh$k6n$1...@news.m-online.net>,
>> Janis Papanagnou <janis_pa...@hotmail.com> wrote:
>>
>>>> 1) You need to reset OPTIND to 1 before you start another attempt of
>>>> option parsing
>>>
>>> This is not correct. You don't need to rest it in a ksh function; it will
>>> be resetted on every function invocation.
>>
>> You are mistaken: OPTIND is a normal variable and it cannot be reset
>> automatically without being in conflict with POSIX.
>
>You are mistaken. Ksh funktions (which, AFAIR, are not specified by POSIX)
>behave exactly that way. You may just try it out. And it's even documented.

It seems you are correct for this non-POSIX case.

The behavior however is not documented. Neither in the ksh88 nor in the ksh93
man page.

Janis Papanagnou

unread,
Feb 10, 2016, 7:05:07 AM2/10/16
to
On 10.02.2016 12:44, Joerg.S...@fokus.fraunhofer.de wrote:
> In article <n9d32f$dk5$1...@news.m-online.net>,
> Janis Papanagnou <janis_pa...@hotmail.com> wrote:
>> On 09.02.2016 15:23, Joerg.S...@fokus.fraunhofer.de wrote:
>>> In article <n9afgh$k6n$1...@news.m-online.net>,
>>> Janis Papanagnou <janis_pa...@hotmail.com> wrote:
>>>
>>>>> 1) You need to reset OPTIND to 1 before you start another attempt of
>>>>> option parsing
>>>>
>>>> This is not correct. You don't need to rest it in a ksh function; it will
>>>> be resetted on every function invocation.
>>>
>>> You are mistaken: OPTIND is a normal variable and it cannot be reset
>>> automatically without being in conflict with POSIX.
>>
>> You are mistaken. Ksh funktions (which, AFAIR, are not specified by POSIX)
>> behave exactly that way. You may just try it out. And it's even documented.
>
> It seems you are correct for this non-POSIX case.

As I said. And the ksh behaviour makes sense. Different from POSIX functions
ksh functions have a scope, with a couple of desirable effects; typeset in
functions declare local variables, trap signal handlers can be defined per
function, option parsing can be done in functions as for the whole program
(without affecting each other! - everything else makes no sense here), etc.

>
> The behavior however is not documented. Neither in the ksh88 nor in the ksh93
> man page.

Read, for example, Bolsky/Korn: "The [new] Kornshell". To quote from there:

"OPTIND is initialized to 1 whenever ksh, a script, or a function
is invoked."

Sadly on http://kornshell.com/doc/ the respective links seem to be defunc
for some time now,[*] and a call of man ksh, or ksh --man will not provide
those details.

Janis

[*] Does someone know a shadow or where it moved to?

Joerg.S...@fokus.fraunhofer.de

unread,
Feb 11, 2016, 6:34:04 AM2/11/16
to
In article <n9f91g$eue$1...@news.m-online.net>,
Since November 2015, most of the related AT&T web space is inaccessible.

BTW: a standard (Bourne or POSIX) shell initializes OPTIND when it starts or
when it uses the "subshell" longjmp() target. This "subshell" longjmp() target
is used only when a script is executed.

Functions are invoked by just calling the shell interpreter function with the
preparsed syntax tree that holds the function code. This does not traverse the
initialization code again.

Given that it is simple to reset OPTIND in functions and given that POSIX did
not standardize this ksh feature, it seems to be wise not to depend on it.

When using the standard function definition method "f() { cmd; }", even ksh
does not behave this way.

Janis Papanagnou

unread,
Feb 11, 2016, 7:20:18 AM2/11/16
to
On 11.02.2016 12:33, Joerg.S...@fokus.fraunhofer.de wrote:
>
> BTW: a standard (Bourne or POSIX) shell initializes OPTIND when it starts or
> when it uses the "subshell" longjmp() target. This "subshell" longjmp() target
> is used only when a script is executed.
>
> Functions are invoked by just calling the shell interpreter function with the
> preparsed syntax tree that holds the function code. This does not traverse the
> initialization code again.
>
> Given that it is simple to reset OPTIND in functions

No, it isn't. If you call functions from functions (etc.) resetting a global
variable would affect the other calls. Only a local scope semantics, like in
ksh functions, will make that work reliably.

> and given that POSIX did
> not standardize this ksh feature, it seems to be wise not to depend on it.

The poster of this thread is in a ksh context, and the statement and response
was clearly stating a ksh function. I see no reason to not depend on that
semantics in ksh.

>
> When using the standard function definition method "f() { cmd; }", even ksh
> does not behave this way.

Of course not; since that is defining a POSIX function, not a ksh function.

Janis

Barry Margolin

unread,
Feb 11, 2016, 11:19:12 AM2/11/16
to
In article <n9hu9t$qgk$1...@news.m-online.net>,
Janis Papanagnou <janis_pa...@hotmail.com> wrote:

> On 11.02.2016 12:33, Joerg.S...@fokus.fraunhofer.de wrote:
> >
> > BTW: a standard (Bourne or POSIX) shell initializes OPTIND when it starts
> > or
> > when it uses the "subshell" longjmp() target. This "subshell" longjmp()
> > target
> > is used only when a script is executed.
> >
> > Functions are invoked by just calling the shell interpreter function with
> > the
> > preparsed syntax tree that holds the function code. This does not traverse
> > the
> > initialization code again.
> >
> > Given that it is simple to reset OPTIND in functions
>
> No, it isn't. If you call functions from functions (etc.) resetting a global
> variable would affect the other calls. Only a local scope semantics, like in
> ksh functions, will make that work reliably.
>
> > and given that POSIX did
> > not standardize this ksh feature, it seems to be wise not to depend on it.
>
> The poster of this thread is in a ksh context, and the statement and response
> was clearly stating a ksh function. I see no reason to not depend on that
> semantics in ksh.

Maybe it's disingenuous, but when I see people writing scripts using the
non-POSIX syntax for function definitions, I don't assume that they
really know all the differences in semantics. In fact, I'm not sure that
most of them even realize that it's nonstandard.

Until this thread, I knew that it was nonstandard syntax, but not that
there were significant differences in how they executed depending on
which syntax was used.

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Janis Papanagnou

unread,
Feb 11, 2016, 5:59:39 PM2/11/16
to
On 11.02.2016 17:19, Barry Margolin wrote:
> In article <n9hu9t$qgk$1...@news.m-online.net>,
> Janis Papanagnou <janis_pa...@hotmail.com> wrote:
>> [ ksh functions ]
>
> Maybe it's disingenuous, but when I see people writing scripts using the
> non-POSIX syntax for function definitions, I don't assume that they
> really know all the differences in semantics. In fact, I'm not sure that
> most of them even realize that it's nonstandard.

We can also observe here in c.u.s that folks use non-standard keywords from
bash (like local), or use ksh(-invented) features but call them "bashisms".
It probably boils down to some people know a bit more what they are doing
and others a bit less. As long as the requirements are clearly defined and
the replies appropriate for the requested context everything should be fine.

Janis
0 new messages